@@ -1,5 +1,44 @@
Imager release history. Older releases can be found in Changes.old
+Imager 0.84 - 20 Jun 2011
+===========
+
+ - Imager no longer inherits from Exporter (unless you're running an
+ old, old perl.
+
+ - Imager can now write progressive JPEGs (it could always read them).
+ https://rt.cpan.org/Ticket/Display.html?id=68691
+
+Bug fixes:
+
+ - re-work, document and test Imager's logging facility.
+ https://rt.cpan.org/Ticket/Display.html?id=65227
+
+ - fix META.yml testing and the generated META.yml
+ https://rt.cpan.org/Ticket/Display.html?id=65235
+
+ - test and add error reporting to to_*() family methods
+
+ - add to_rgb_double() method.
+ https://rt.cpan.org/Ticket/Display.html?id=65101
+
+ - Imager no longer exports anything by default
+ https://rt.cpan.org/Ticket/Display.html?id=65228
+
+ - convert colors to grayscale if the supplied (or generated) palette
+ contains only grays when performing error diffusion color
+ translation.
+ https://rt.cpan.org/Ticket/Display.html?id=68508
+
+ - writing a paletted image to GIF wouldn't always use the colors
+ supplied (or generated, eg. via make_colors => "mono"), which was
+ confusing at best.
+ https://rt.cpan.org/Ticket/Display.html?id=67912
+
+ - replace (imager|tony)@imager.perl.org in the doc, since I don't
+ plan to continue receiving mail at that address.
+ https://rt.cpan.org/Ticket/Display.html?id=68591
+
Imager 0.83 - 21 May 2011
===========
@@ -49,7 +49,7 @@ Imager, Imager::Filter::DynTest
=head1 AUTHOR
-Tony Cook <tony@imager.perl.org>
+Tony Cook <tonyc@cpan.org>
=cut
@@ -11,7 +11,7 @@ my %opts =
);
my $MM_ver = eval $ExtUtils::MakeMaker::VERSION;
if ($MM_ver > 6.06) {
- $opts{AUTHOR} = 'Tony Cook <tony@imager.perl.org>';
+ $opts{AUTHOR} = 'Tony Cook <tonyc@cpan.org>';
$opts{ABSTRACT} = 'Color Count an Imager image';
}
@@ -11,7 +11,7 @@ my %opts =
);
my $MM_ver = eval $ExtUtils::MakeMaker::VERSION;
if ($MM_ver > 6.06) {
- $opts{AUTHOR} = 'Tony Cook <tony@imager.perl.org>';
+ $opts{AUTHOR} = 'Tony Cook <tonyc@cpan.org>';
$opts{ABSTRACT} = 'Demo Imager filter extension';
}
@@ -5,7 +5,7 @@ use vars qw($VERSION @ISA);
@ISA = qw(Imager::Font);
BEGIN {
- $VERSION = "0.79";
+ $VERSION = "0.80";
eval {
require XSLoader;
@@ -218,7 +218,7 @@ supported font files, so I've renamed it.
=head1 AUTHOR
-Tony Cook <tony@imager.perl.org>
+Tony Cook <tonyc@cpan.org>
=head1 SEE ALSO
@@ -54,12 +54,8 @@ else {
resources =>
{
homepage => "http://imager.perl.org/",
- repository =>
- {
- url => "http://imager.perl.org/svn/trunk/Imager/FT2",
- web => "http://imager.perl.org/svnweb/public/browse/trunk/Imager/FT2",
- type => "svn",
- },
+ repository => "git://git.imager.perl.org/imager.git",
+ bugtracker => "http://rt.cpan.org/NoAuth/Bugs.html?Dist=Imager",
},
};
$opts{PREREQ_PM} =
@@ -106,7 +102,7 @@ if ($probe_res) {
if $probe_res->{LDDLFLAGS};
if ($MM_ver > 6.06) {
- $opts{AUTHOR} = 'Tony Cook <tony@imager.perl.org>';
+ $opts{AUTHOR} = 'Tony Cook <tonyc@cpan.org>';
$opts{ABSTRACT} = 'FreeType 2 font driver for Imager';
}
@@ -0,0 +1,10 @@
+Imager::Font::FT2 provides font support to Imager via the FreeType 2
+library.
+
+It requires libfreetype and its development header files to be
+installed.
+
+This is currently shipped as part of Imager, but but Imager may
+install with out installing Imager::Font::FT2, if your module or
+application requires FreeType 2 support then add Imager::Font::FT2 as
+a prerequisite.
@@ -48,7 +48,7 @@ This filter has no parameters.
Original by Arnar M. Hrafnkelsson.
-Adapted by Tony Cook <tony@imager.perl.org>
+Adapted by Tony Cook <tonyc@cpan.org>
=head1 SEE ALSO
@@ -11,7 +11,7 @@ my %opts =
);
my $MM_ver = eval $ExtUtils::MakeMaker::VERSION;
if ($MM_ver > 6.06) {
- $opts{AUTHOR} = 'Tony Cook <tony@imager.perl.org>';
+ $opts{AUTHOR} = 'Tony Cook <tonyc@cpan.org>';
$opts{ABSTRACT} = 'Flines Imager filter extension';
}
@@ -4,7 +4,7 @@ use Imager;
use vars qw($VERSION @ISA);
BEGIN {
- $VERSION = "0.78";
+ $VERSION = "0.79";
eval {
require XSLoader;
@@ -121,7 +121,7 @@ Imager's GIF support is documented in L<Imager::Files>.
=head1 AUTHOR
-Tony Cook <tony@imager.perl.org>
+Tony Cook <tonyc@cpan.org>
=head1 SEE ALSO
@@ -38,7 +38,7 @@ else {
$opts{TYPEMAPS} = [ Imager::ExtUtils->typemap ];
# Imager required configure through use
- my @Imager_req = ( Imager => "0.78" );
+ my @Imager_req = ( Imager => "0.84" );
if ($MM_ver >= 6.46) {
$opts{META_MERGE} =
{
@@ -54,12 +54,8 @@ else {
resources =>
{
homepage => "http://imager.perl.org/",
- repository =>
- {
- url => "http://imager.perl.org/svn/trunk/Imager/GIF",
- web => "http://imager.perl.org/svnweb/public/browse/trunk/Imager/GIF",
- type => "svn",
- },
+ repository => "git://git.imager.perl.org/imager.git",
+ bugtracker => "http://rt.cpan.org/NoAuth/Bugs.html?Dist=Imager",
},
};
$opts{PREREQ_PM} =
@@ -92,7 +88,7 @@ if ($probe_res) {
$opts{INC} = "@inc";
if ($MM_ver > 6.06) {
- $opts{AUTHOR} = 'Tony Cook <tony@imager.perl.org>';
+ $opts{AUTHOR} = 'Tony Cook <tonyc@cpan.org>';
$opts{ABSTRACT} = 'GIF Image file support';
}
@@ -0,0 +1,7 @@
+Imager::File::GIF provides GIF file format support for Imager.
+
+It requires libgif to be installed, including development headers.
+
+This is currently shipped as part of Imager, but Imager may install
+with out installing Imager::File::GIF, so if you need GIF support, add
+a dependency on Imager::File::GIF.
@@ -1229,23 +1229,26 @@ in_palette(i_color *c, i_quantize *quant, int size) {
}
/*
-=item has_common_palette(imgs, count, quant, want_trans)
+=item has_common_palette(imgs, count, quant)
-Tests if all the given images are paletted and have a common palette,
-if they do it builds that palette.
+Tests if all the given images are paletted and their colors are in the
+palette produced.
-A possible improvement might be to eliminate unused colors in the
-images palettes.
+Previously this would build a consolidated palette from the source,
+but that meant that if the caller supplied a static palette (or
+specified a fixed palette like "webmap") then we wouldn't be
+quantizing to the caller specified palette.
=cut
*/
+
static int
-has_common_palette(i_img **imgs, int count, i_quantize *quant,
- int want_trans) {
+has_common_palette(i_img **imgs, int count, i_quantize *quant) {
int size = quant->mc_count;
int i;
int imgn;
char used[256];
+ int col_count;
/* we try to build a common palette here, if we can manage that, then
that's the palette we use */
@@ -1277,25 +1280,22 @@ has_common_palette(i_img **imgs, int count, i_quantize *quant,
memset(used, 1, sizeof(used));
}
- for (i = 0; i < i_colorcount(imgs[imgn]); ++i) {
+ col_count = i_colorcount(imgs[imgn]);
+ for (i = 0; i < col_count; ++i) {
i_color c;
i_getcolors(imgs[imgn], i, &c, 1);
if (used[i]) {
- if (in_palette(&c, quant, size) < 0) {
- if (size < quant->mc_size) {
- quant->mc_colors[size++] = c;
- }
- else {
- /* oops, too many colors */
- return 0;
- }
+ if (in_palette(&c, quant, quant->mc_count) < 0) {
+ mm_log((1, " color not found in palette, no palette shortcut\n"));
+
+ return 0;
}
}
}
}
- quant->mc_count = size;
+ mm_log((1, " all colors found in palette, palette shortcut\n"));
return 1;
}
@@ -1424,13 +1424,9 @@ i_writegif_low(i_quantize *quant, GifFileType *gf, i_img **imgs, int count) {
mm_log((2, " reserving color for transparency\n"));
--quant->mc_size;
}
- if (has_common_palette(glob_imgs, glob_img_count, quant, want_trans)) {
- glob_paletted = 1;
- }
- else {
- glob_paletted = 0;
- i_quant_makemap(quant, glob_imgs, glob_img_count);
- }
+
+ i_quant_makemap(quant, glob_imgs, glob_img_count);
+ glob_paletted = has_common_palette(glob_imgs, glob_img_count, quant);
glob_color_count = quant->mc_count;
quant->mc_colors = orig_colors;
}
@@ -1451,14 +1447,10 @@ i_writegif_low(i_quantize *quant, GifFileType *gf, i_img **imgs, int count) {
}
else {
want_trans = quant->transp != tr_none && imgs[0]->channels == 4;
- if (has_common_palette(imgs, 1, quant, want_trans)) {
- colors_paletted = 1;
- }
- else {
- colors_paletted = 0;
- i_quant_makemap(quant, imgs, 1);
- }
+ i_quant_makemap(quant, imgs, 1);
+ colors_paletted = has_common_palette(imgs, 1, quant);
}
+
if ((map = make_gif_map(quant, imgs[0], want_trans)) == NULL) {
myfree(glob_colors);
myfree(localmaps);
@@ -1525,13 +1517,8 @@ i_writegif_low(i_quantize *quant, GifFileType *gf, i_img **imgs, int count) {
to give room for a transparency colour */
if (want_trans && quant->mc_size == 256)
--quant->mc_size;
- if (has_common_palette(imgs, 1, quant, want_trans)) {
- colors_paletted = 1;
- }
- else {
- colors_paletted = 0;
- i_quant_makemap(quant, imgs, 1);
- }
+ i_quant_makemap(quant, imgs, 1);
+ colors_paletted = has_common_palette(imgs, 1, quant);
if ((map = make_gif_map(quant, imgs[0], want_trans)) == NULL) {
myfree(glob_colors);
myfree(localmaps);
@@ -1639,7 +1626,7 @@ i_writegif_low(i_quantize *quant, GifFileType *gf, i_img **imgs, int count) {
if (want_trans && quant->mc_size == 256)
--quant->mc_size;
- if (has_common_palette(imgs+imgn, 1, quant, want_trans)) {
+ if (has_common_palette(imgs+imgn, 1, quant)) {
result = quant_paletted(quant, imgs[imgn]);
}
else {
@@ -0,0 +1,47 @@
+#!perl -w
+use strict;
+use Test::More tests => 9;
+use Imager;
+use Imager::Test qw(test_image);
+
+-d "testout" or mkdir "testout";
+
+Imager->open_log(log => "testout/t30fixed.log");
+
+{
+ # RT 67912
+ # previously, if you tried to write a paletted image to GIF:
+ # - specified a fixed palette with make_colors => "mono", "web" or "none"
+ # - there was room for the colors in the image in the rest of the
+ # palette (or they were found in the generated palette)
+ # the GIF would be written with essentially it's original palette
+ # instead of the specified palette
+ #
+ # This was confusing, especially if you specified a restricted
+ # palette such as mono or a small greyscale ramp
+
+ my $src = test_image();
+ ok($src, "make source image");
+ my $pal = $src->to_paletted(max_colors => 250);
+ ok($pal, "make paletted version");
+ cmp_ok($pal->colorcount, "<=", 250, "make sure not too many colors");
+
+ my $mono = $src->to_paletted(make_colors => "mono", translate => "errdiff");
+ ok($mono, "make mono image directly");
+ ok($mono->write(file => "testout/t30monodirect.gif", type => "gif"),
+ "save mono direct image");
+
+ Imager->log("Save manually paletted version\n");
+ ok($pal->write(file => "testout/t30color.gif"),
+ "save generated palette version");
+ Imager->log("Save mono version\n");
+ ok($pal->write(file => "testout/t30monoind.gif", type => "gif",
+ make_colors => "mono", translate => "errdiff"),
+ "write paletted with mono colormap");
+
+ my $rd = Imager->new(file => "testout/t30monoind.gif", type => "gif");
+ ok($rd, "read it back in");
+ is($rd->colorcount, 2, "should only have 2 colors");
+}
+
+Imager->close_log;
@@ -167,7 +167,7 @@ Imager's MS Icon support is documented in L<Imager::Files>.
=head1 AUTHOR
-Tony Cook <tony@imager.perl.org>
+Tony Cook <tonyc@cpan.org>
=head1 SEE ALSO
@@ -12,7 +12,7 @@ my %opts =
);
my $MM_ver = eval $ExtUtils::MakeMaker::VERSION;
if ($MM_ver > 6.06) {
- $opts{AUTHOR} = 'Tony Cook <tony@imager.perl.org>';
+ $opts{AUTHOR} = 'Tony Cook <tonyc@cpan.org>';
$opts{ABSTRACT} = 'Icon Image file support';
}
@@ -1533,7 +1533,7 @@ write_mask(i_io_glue_t *ig, ico_image_t const *image, int *error) {
=head1 AUTHOR
-Tony Cook <tony@imager.perl.org>
+Tony Cook <tonyc@cpan.org>
=head1 REVISION
@@ -94,14 +94,6 @@ use Imager::Font;
);
@EXPORT=qw(
- init_log
- i_list_formats
- i_has_format
- malloc_state
- i_color_new
-
- i_img_empty
- i_img_empty_ch
);
%EXPORT_TAGS=
@@ -145,8 +137,11 @@ my %defaults;
BEGIN {
require Exporter;
- @ISA = qw(Exporter);
- $VERSION = '0.83';
+ my $ex_version = eval $Exporter::VERSION;
+ if ($ex_version < 5.57) {
+ @ISA = qw(Exporter);
+ }
+ $VERSION = '0.84';
eval {
require XSLoader;
XSLoader::load(Imager => $VERSION);
@@ -451,15 +446,14 @@ sub import {
}
sub init_log {
- i_init_log($_[0],$_[1]);
- i_log_entry("Imager $VERSION starting\n", 1);
+ Imager->open_log(log => $_[0], level => $_[1]);
}
sub init {
my %parms=(loglevel=>1,@_);
if ($parms{'log'}) {
- init_log($parms{'log'},$parms{'loglevel'});
+ Imager->open_log(log => $parms{log}, level => $parms{loglevel});
}
if (exists $parms{'warn_obsolete'}) {
@@ -473,6 +467,42 @@ sub init {
}
}
+{
+ my $is_logging = 0;
+
+ sub open_log {
+ my $class = shift;
+ my (%opts) = ( loglevel => 1, @_ );
+
+ $is_logging = i_init_log($opts{log}, $opts{loglevel});
+ unless ($is_logging) {
+ Imager->_set_error(Imager->_error_as_msg());
+ return;
+ }
+
+ Imager->log("Imager $VERSION starting\n", 1);
+
+ return $is_logging;
+ }
+
+ sub close_log {
+ i_init_log(undef, -1);
+ $is_logging = 0;
+ }
+
+ sub log {
+ my ($class, $message, $level) = @_;
+
+ defined $level or $level = 1;
+
+ i_log_entry($message, $level);
+ }
+
+ sub is_logging {
+ return $is_logging;
+ }
+}
+
END {
if ($DEBUG) {
print "shutdown code\n";
@@ -931,24 +961,21 @@ sub to_paletted {
return;
}
- my $result = Imager->new;
- $result->{IMG} = i_img_to_pal($self->{IMG}, $opts);
-
- #print "Type ", i_img_type($result->{IMG}), "\n";
+ $self->_valid_image
+ or return;
- if ($result->{IMG}) {
- return $result;
- }
- else {
- $self->{ERRSTR} = $self->_error_as_msg;
+ my $result = Imager->new;
+ unless ($result->{IMG} = i_img_to_pal($self->{IMG}, $opts)) {
+ $self->_set_error(Imager->_error_as_msg);
return;
}
+
+ return $result;
}
-# convert a paletted (or any image) to an 8-bit/channel RGB images
+# convert a paletted (or any image) to an 8-bit/channel RGB image
sub to_rgb8 {
my $self = shift;
- my $result;
unless (defined wantarray) {
my @caller = caller;
@@ -956,30 +983,57 @@ sub to_rgb8 {
return;
}
- if ($self->{IMG}) {
- $result = Imager->new;
- $result->{IMG} = i_img_to_rgb($self->{IMG})
- or undef $result;
+ $self->_valid_image
+ or return;
+
+ my $result = Imager->new;
+ unless ($result->{IMG} = i_img_to_rgb($self->{IMG})) {
+ $self->_set_error(Imager->_error_as_msg());
+ return;
}
return $result;
}
-# convert a paletted (or any image) to an 8-bit/channel RGB images
+# convert a paletted (or any image) to a 16-bit/channel RGB image
sub to_rgb16 {
my $self = shift;
- my $result;
unless (defined wantarray) {
my @caller = caller;
- warn "to_rgb16() called in void context - to_rgb8() returns the converted image at $caller[1] line $caller[2]\n";
+ warn "to_rgb16() called in void context - to_rgb16() returns the converted image at $caller[1] line $caller[2]\n";
return;
}
- if ($self->{IMG}) {
- $result = Imager->new;
- $result->{IMG} = i_img_to_rgb16($self->{IMG})
- or undef $result;
+ $self->_valid_image
+ or return;
+
+ my $result = Imager->new;
+ unless ($result->{IMG} = i_img_to_rgb16($self->{IMG})) {
+ $self->_set_error(Imager->_error_as_msg());
+ return;
+ }
+
+ return $result;
+}
+
+# convert a paletted (or any image) to an double/channel RGB image
+sub to_rgb_double {
+ my $self = shift;
+
+ unless (defined wantarray) {
+ my @caller = caller;
+ warn "to_rgb16() called in void context - to_rgb_double() returns the converted image at $caller[1] line $caller[2]\n";
+ return;
+ }
+
+ $self->_valid_image
+ or return;
+
+ my $result = Imager->new;
+ unless ($result->{IMG} = i_img_to_drgb($self->{IMG})) {
+ $self->_set_error(Imager->_error_as_msg());
+ return;
}
return $result;
@@ -4253,6 +4307,9 @@ box() - L<Imager::Draw/box()> - draw a filled or outline box.
circle() - L<Imager::Draw/circle()> - draw a filled circle
+close_log() - L<Imager::ImageTypes/close_log()> - close the Imager
+debugging log.
+
colorcount() - L<Imager::ImageTypes/colorcount()> - the number of
colors in an image's palette (paletted images only)
@@ -4336,10 +4393,16 @@ is_bilevel() - L<Imager::ImageTypes/is_bilevel()> - returns whether
image write functions should write the image in their bilevel (blank
and white, no gray levels) format
+is_logging() L<Imager::ImageTypes/is_logging()> - test if the debug
+log is active.
+
line() - L<Imager::Draw/line()> - draw an interval
load_plugin() - L<Imager::Filters/load_plugin()>
+log() - L<Imager::ImageTypes/log()> - send a message to the debugging
+log.
+
map() - L<Imager::Transformations/"Color Mappings"> - remap color
channel values
@@ -4365,6 +4428,8 @@ NF() - L<Imager::Handy/NF()>
open() - L<Imager::Files> - an alias for read()
+open_log() - L<Imager::ImageTypes/open_log()> - open the debug log.
+
=for stopwords IPTC
parseiptc() - L<Imager::Files/parseiptc()> - parse IPTC data from a JPEG
@@ -4431,6 +4496,9 @@ to_rgb16() - L<Imager::ImageTypes/to_rgb16()>
to_rgb8() - L<Imager::ImageTypes/to_rgb8()>
+to_rgb_double() - L<Imager::ImageTypes/to_rgb_double()> - convert to
+double per sample image.
+
transform() - L<Imager::Engines/"transform()">
transform2() - L<Imager::Engines/"transform2()">
@@ -4701,7 +4769,7 @@ it will be delayed until I get a chance to write them.
=head1 AUTHOR
-Tony Cook <tony@imager.perl.org> is the current maintainer for Imager.
+Tony Cook <tonyc@cpan.org> is the current maintainer for Imager.
Arnar M. Hrafnkelsson is the original author of Imager.
@@ -862,10 +862,11 @@ validate_i_ppal(i_img *im, i_palidx const *indexes, int count) {
#define ICLF_new_internal(r, g, b, a) i_fcolor_new((r), (g), (b), (a))
#define ICLF_DESTROY(cl) i_fcolor_destroy(cl)
-
-/* the m_init_log() function was called init_log(), renamed to reduce
- potential naming conflicts */
-#define init_log m_init_log
+#ifdef IMAGER_LOG
+#define i_log_enabled() 1
+#else
+#define i_log_enabled() 0
+#endif
#if i_int_hlines_testing()
@@ -1325,20 +1326,24 @@ i_sametype_chans(im, x, y, channels)
int y
int channels
-void
+int
i_init_log(name_sv,level)
SV* name_sv
int level
PREINIT:
const char *name = SvOK(name_sv) ? SvPV_nolen(name_sv) : NULL;
CODE:
- i_init_log(name, level);
+ RETVAL = i_init_log(name, level);
+ OUTPUT:
+ RETVAL
void
i_log_entry(string,level)
char* string
int level
+int
+i_log_enabled()
void
i_img_exorcise(im)
@@ -3524,6 +3529,10 @@ i_img_double_new(x, y, ch)
int y
int ch
+Imager::ImgRaw
+i_img_to_drgb(im)
+ Imager::ImgRaw im
+
undef_int
i_tags_addn(im, name, code, idata)
Imager::ImgRaw im
@@ -4,7 +4,7 @@ use Imager;
use vars qw($VERSION @ISA);
BEGIN {
- $VERSION = "0.78";
+ $VERSION = "0.79";
eval {
require XSLoader;
@@ -80,7 +80,7 @@ Imager's JPEG support is documented in L<Imager::Files>.
=head1 AUTHOR
-Tony Cook <tony@imager.perl.org>
+Tony Cook <tonyc@cpan.org>
=head1 SEE ALSO
@@ -54,12 +54,8 @@ else {
resources =>
{
homepage => "http://imager.perl.org/",
- repository =>
- {
- url => "http://imager.perl.org/svn/trunk/Imager/JPEG",
- web => "http://imager.perl.org/svnweb/public/browse/trunk/Imager/JPEG",
- type => "svn",
- },
+ repository => "git://git.imager.perl.org/imager.git",
+ bugtracker => "http://rt.cpan.org/NoAuth/Bugs.html?Dist=Imager",
},
};
$opts{PREREQ_PM} =
@@ -92,7 +88,7 @@ if ($probe_res) {
$opts{INC} = "@inc";
if ($MM_ver > 6.06) {
- $opts{AUTHOR} = 'Tony Cook <tony@imager.perl.org>';
+ $opts{AUTHOR} = 'Tony Cook <tonyc@cpan.org>';
$opts{ABSTRACT} = 'JPEG Image file support';
}
@@ -0,0 +1,7 @@
+Imager::File::JPEG provides JPEG file format support for Imager.
+
+It requires libjpeg to be installed.
+
+This is currently shipped as part of Imager, but Imager may install
+with out installing Imager::File::JPEG, so if you need JPEG support,
+add a dependency on Imager::File::JPEG.
@@ -1576,7 +1576,7 @@ http://www.exif.org/
=head1 AUTHOR
-Tony Cook <tony@imager.perl.org>
+Tony Cook <tonyc@cpan.org>
=head1 REVISION
@@ -543,6 +543,14 @@ i_readjpeg_wiol(io_glue *data, int length, char** iptc_itext, int *itlength) {
i_tags_set_float2(&im->tags, "i_yres", 0, yres, 6);
}
+ /* I originally used jpeg_has_multiple_scans() here, but that can
+ * return true for non-progressive files too. The progressive_mode
+ * member is available at least as far back as 6b and does the right
+ * thing.
+ */
+ i_tags_setn(&im->tags, "jpeg_progressive",
+ cinfo.progressive_mode ? 1 : 0);
+
(void) jpeg_finish_decompress(&cinfo);
jpeg_destroy_decompress(&cinfo);
*itlength=tlength;
@@ -567,6 +575,7 @@ i_writejpeg_wiol(i_img *im, io_glue *ig, int qfactor) {
double xres, yres;
int comment_entry;
int want_channels = im->channels;
+ int progressive = 0;
struct jpeg_compress_struct cinfo;
struct my_error_mgr jerr;
@@ -618,6 +627,12 @@ i_writejpeg_wiol(i_img *im, io_glue *ig, int qfactor) {
jpeg_set_defaults(&cinfo);
jpeg_set_quality(&cinfo, quality, TRUE); /* limit to baseline-JPEG values */
+ if (!i_tags_get_int(&im->tags, "jpeg_progressive", 0, &progressive))
+ progressive = 0;
+ if (progressive) {
+ jpeg_simple_progression(&cinfo);
+ }
+
got_xres = i_tags_get_float(&im->tags, "i_xres", 0, &xres);
got_yres = i_tags_get_float(&im->tags, "i_yres", 0, &yres);
if (!i_tags_get_int(&im->tags, "i_aspect_only", 0,&aspect_only))
@@ -2,7 +2,7 @@
use strict;
use Imager qw(:all);
use Test::More;
-use Imager::Test qw(is_color_close3 test_image_raw);
+use Imager::Test qw(is_color_close3 test_image_raw test_image is_image);
-d "testout" or mkdir "testout";
@@ -11,7 +11,7 @@ init_log("testout/t101jpeg.log",1);
$Imager::formats{"jpeg"}
or plan skip_all => "no jpeg support";
-plan tests => 94;
+plan tests => 101;
my $green=i_color_new(0,255,0,255);
my $blue=i_color_new(0,0,255,255);
@@ -408,4 +408,27 @@ SKIP:
ok(grep($_ eq 'jpeg', Imager->write_types), "check jpeg in write types");
}
+{ # progressive JPEG
+ # https://rt.cpan.org/Ticket/Display.html?id=68691
+ my $im = test_image();
+ my $progim = $im->copy;
+ ok($progim->write(file => "testout/t10prog.jpg", type => "jpeg",
+ jpeg_progressive => 1),
+ "write progressive jpeg");
+
+ my $rdprog = Imager->new(file => "testout/t10prog.jpg");
+ ok($rdprog, "read progressive jpeg");
+ my @prog = $rdprog->tags(name => "jpeg_progressive");
+ is($prog[0], 1, "check progressive flag set on read");
+
+ my $data;
+ ok($im->write(data => \$data, type => "jpeg"),
+ "save as non-progressive to compare");
+ my $norm = Imager->new(data => $data);
+ ok($norm, "read non-progressive file");
+ my @nonprog = $norm->tags(name => "jpeg_progressive");
+ is($nonprog[0], 0, "check progressive flag 0 for non prog file");
+
+ is_image($rdprog, $norm, "prog vs norm should be the same image");
+}
@@ -66,6 +66,7 @@ FT2/FT2.pm
FT2/FT2.xs
FT2/imft2.h
FT2/Makefile.PL
+FT2/README
FT2/t/t10ft2.t
FT2/typemap
gaussian.im
@@ -74,8 +75,10 @@ GIF/GIF.xs
GIF/imgif.c
GIF/imgif.h
GIF/Makefile.PL
+GIF/README
GIF/t/t10gif.t
GIF/t/t20new.t
+GIF/t/t30fixed.t
GIF/testimg/badindex.gif GIF with a bad color index
GIF/testimg/bandw.gif
GIF/testimg/expected.gif
@@ -132,7 +135,8 @@ imextdef.h
imextpl.h Included by external modules for Perl API access
imextpltypes.h Define Perl API function table type
imexttypes.h Define API function table type
-img16.c
+img16.c Implements 16-bit/sample images
+img8.c Implements 8-bit/sample images
imgdouble.c Implements double/sample images
imio.h
immacros.h
@@ -150,6 +154,7 @@ JPEG/imjpeg.h
JPEG/JPEG.pm
JPEG/JPEG.xs
JPEG/Makefile.PL
+JPEG/README
JPEG/t/t00load.t
JPEG/t/t10jpeg.t Test jpeg support
JPEG/testimg/209_yonge.jpg Regression test: #17981
@@ -175,7 +180,7 @@ lib/Imager/Font/BBox.pm
lib/Imager/Font/FreeType2.pm
lib/Imager/Font/Image.pm
lib/Imager/Font/Truetype.pm
-lib/Imager/Font/Type1.pm Compatibilty wrapper for Imager::Font::T1
+lib/Imager/Font/Type1.pm Compatibility wrapper for Imager::Font::T1
lib/Imager/Font/Wrap.pm
lib/Imager/Fountain.pm
lib/Imager/Handy.pod
@@ -206,7 +211,6 @@ MANIFEST
MANIFEST.SKIP
map.c
maskimg.c
-META.yml Module meta-data
palimg.c
paste.im
plug.h
@@ -215,6 +219,7 @@ PNG/impng.h
PNG/Makefile.PL
PNG/PNG.pm
PNG/PNG.xs
+PNG/README
PNG/t/00load.t
PNG/t/10png.t Test png support
PNG/testimg/palette.png
@@ -326,6 +331,8 @@ t/t91pod.t Test POD with Test::Pod
t/t92samples.t
t/t93podcover.t POD Coverage tests
t/t94kwalitee.t Various "kwalitee" tests
+t/t95log.t
+t/t98meta.t
t/t99thread.t Test wrt to perl threads
t/tr18561.t Regression tests
t/tr18561b.t
@@ -419,6 +426,7 @@ tga.c Reading and writing Targa files
TIFF/imtiff.c
TIFF/imtiff.h
TIFF/Makefile.PL
+TIFF/README
TIFF/t/t10tiff.t Test tiff support
TIFF/testimg/alpha.tif Alpha scaling test image
TIFF/testimg/comp4.bmp Compressed 4-bit/pixel BMP
@@ -457,7 +465,9 @@ W32/fontfiles/ExistenceTest.ttf
W32/imw32.h
W32/lib/Imager/Font/Win32.pm
W32/Makefile.PL
+W32/README
W32/t/t10win32.t Tests Win32 GDI font support
W32/W32.pm
W32/W32.xs
W32/win32.c Implements font support through Win32 GDI
+META.yml Module meta-data (added by MakeMaker)
@@ -63,6 +63,7 @@ Makefile\.old$
^SGI/testout/
^TIFF/testout/
^T1/testout/
+^W32/testout/
# generated from .xs
^CountColor/CountColor\.c$
@@ -76,9 +77,12 @@ Makefile\.old$
^SGI/SGI\.c$
^TIFF/TIFF\.c$
^T1/T1\.c$
+^W32/W32\.c$
^.*/Changes$
^.*/MANIFEST(\.SKIP)?$
+^.+/inc/Devel/CheckLib\.pm$
+^.+/blib/
^blib/
^Flines/Flines\.c$
^Imager\.c$
@@ -113,3 +117,12 @@ Makefile\.old$
^samples/logo$
^samples/transform\.pl$
^samples/transform1\.ppm$
+
+# Win32 junk
+^(.+/)?dll\.(base|exp)$
+^(.+/)?\w+\.def$
+^(.+/)?\w+\_def.old$
+\.exe$
+
+# sub-module build junk
+\.bak$
@@ -1,9 +1,9 @@
--- #YAML:1.0
name: Imager
-version: 0.83
+version: 0.84
abstract: Perl extension for Generating 24 bit Images
author:
- - Tony Cook <tony@imager.perl.org>, Arnar M. Hrafnkelsson
+ - Tony Cook <tonyc@cpan.org>, Arnar M. Hrafnkelsson
license: perl
distribution_type: module
configure_requires:
@@ -13,14 +13,9 @@ build_requires:
requires:
Test::More: 0.47
resources:
- bugtracker:
- mailto: bug-Imager@rt.cpan.org
- web: http://rt.cpan.org/NoAuth/Bugs.html?Dist=Imager
- homepage: http://imager.perl.org/
- repository:
- type: git
- url: git://git.imager.perl.org/imager.git
- web: http://git.imager.perl.org/imager.git
+ bugtracker: http://rt.cpan.org/NoAuth/Bugs.html?Dist=Imager
+ homepage: http://imager.perl.org/
+ repository: git://git.imager.perl.org/imager.git
no_index:
directory:
- t
@@ -163,7 +163,7 @@ my @objs = qw(Imager.o draw.o polygon.o image.o io.o iolayer.o
log.o gaussian.o conv.o pnm.o raw.o feat.o font.o combine.o
filters.o dynaload.o stackmach.o datatypes.o
regmach.o trans2.o quant.o error.o convert.o
- map.o tags.o palimg.o maskimg.o img16.o rotate.o
+ map.o tags.o palimg.o maskimg.o img8.o img16.o rotate.o
bmp.o tga.o color.o fills.o imgdouble.o limits.o hlines.o
imext.o scale.o rubthru.o render.o paste.o compose.o flip.o);
@@ -192,7 +192,7 @@ if ($coverage) {
# eval to prevent warnings about versions with _ in them
my $MM_ver = eval $ExtUtils::MakeMaker::VERSION;
if ($MM_ver > 6.06) {
- $opts{AUTHOR} = 'Tony Cook <tony@imager.perl.org>, Arnar M. Hrafnkelsson';
+ $opts{AUTHOR} = 'Tony Cook <tonyc@cpan.org>, Arnar M. Hrafnkelsson';
$opts{ABSTRACT} = 'Perl extension for Generating 24 bit Images';
}
@@ -220,17 +220,8 @@ if ($MM_ver >= 6.46) {
resources =>
{
homepage => "http://imager.perl.org/",
- repository =>
- {
- url => "git://git.imager.perl.org/imager.git",
- web => "http://git.imager.perl.org/imager.git",
- type => "git",
- },
- bugtracker =>
- {
- web => "http://rt.cpan.org/NoAuth/Bugs.html?Dist=Imager",
- mailto => 'bug-Imager@rt.cpan.org',
- },
+ repository => "git://git.imager.perl.org/imager.git",
+ bugtracker => "http://rt.cpan.org/NoAuth/Bugs.html?Dist=Imager",
},
};
}
@@ -11,7 +11,7 @@ my %opts =
);
my $MM_ver = eval $ExtUtils::MakeMaker::VERSION;
if ($MM_ver > 6.06) {
- $opts{AUTHOR} = 'Tony Cook <tony@imager.perl.org>';
+ $opts{AUTHOR} = 'Tony Cook <tonyc@cpan.org>';
$opts{ABSTRACT} = 'Mandelbrot Imager filter extension';
}
@@ -82,7 +82,7 @@ if the sequence tend towards infinity.
Original by Arnar M. Hrafnkelsson.
-Adapted and expanded by Tony Cook <tony@imager.perl.org>
+Adapted and expanded by Tony Cook <tonyc@cpan.org>
=head1 SEE ALSO
@@ -54,12 +54,8 @@ else {
resources =>
{
homepage => "http://imager.perl.org/",
- repository =>
- {
- url => "http://imager.perl.org/svn/trunk/Imager/PNG",
- web => "http://imager.perl.org/svnweb/public/browse/trunk/Imager/PNG",
- type => "svn",
- },
+ repository => "git://git.imager.perl.org/imager.git",
+ bugtracker => "http://rt.cpan.org/NoAuth/Bugs.html?Dist=Imager",
},
};
$opts{PREREQ_PM} =
@@ -112,7 +108,7 @@ if ($probe_res) {
$opts{INC} = "@inc";
if ($MM_ver > 6.06) {
- $opts{AUTHOR} = 'Tony Cook <tony@imager.perl.org>';
+ $opts{AUTHOR} = 'Tony Cook <tonyc@cpan.org>';
$opts{ABSTRACT} = 'PNG Image file support';
}
@@ -4,7 +4,7 @@ use Imager;
use vars qw($VERSION @ISA);
BEGIN {
- $VERSION = "0.78";
+ $VERSION = "0.79";
eval {
require XSLoader;
@@ -74,7 +74,7 @@ Imager's PNG support is documented in L<Imager::Files>.
=head1 AUTHOR
-Tony Cook <tony@imager.perl.org>
+Tony Cook <tonyc@cpan.org>
=head1 SEE ALSO
@@ -0,0 +1,7 @@
+Imager::File::PNG provides PNG file format support for Imager.
+
+It requires libpng to be installed.
+
+This is currently shipped as part of Imager, but Imager may install
+with out installing Imager::File::PNG, so if you need PNG support,
+add a dependency on Imager::File::PNG.
@@ -1,6 +1,6 @@
================================================================
Copyright (c) 1999-2004 Arnar M. Hrafnkelsson. All rights reserved.
-Copyright (c) 2004-2010 Anthony Cook.
+Copyright (c) 2004-2011 Anthony Cook.
This program is free software; you can redistribute it and/or
modify it under the same terms as Perl itself.
@@ -11,7 +11,7 @@ copyrighted by Adobe. See adobe.txt for license information.
>> THIS SOFTWARE COMES WITH ABSOLUTELY NO WARRANTY WHATSOEVER <<
If you like or hate Imager, please let me know by sending mail
-to imager@imager.perl.org - I love feedback.
+to tonyc@cpan.org - I love feedback.
================================================================
@@ -75,7 +75,7 @@ If either fails do take a peek at the file errep.perl. It's creates a
file report.txt. This is some information which will help me discover
where the problem is so I can try to fix it in future releases. If
you find running it ok (just remember - no warranty!) please send the
-report.txt via email to imager@imager.perl.org.
+report.txt via email to tonyc@cpan.org.
Troubleshooting tips:
@@ -12,7 +12,7 @@ my %opts =
);
my $MM_ver = eval $ExtUtils::MakeMaker::VERSION;
if ($MM_ver > 6.06) {
- $opts{AUTHOR} = 'Tony Cook <tony@imager.perl.org>';
+ $opts{AUTHOR} = 'Tony Cook <tonyc@cpan.org>';
$opts{ABSTRACT} = 'SGI Image file support';
}
@@ -80,7 +80,7 @@ Imager's MS Icon support is documented in L<Imager::Files>.
=head1 AUTHOR
-Tony Cook <tony@imager.perl.org>
+Tony Cook <tonyc@cpan.org>
=head1 SEE ALSO
@@ -54,12 +54,8 @@ else {
resources =>
{
homepage => "http://imager.perl.org/",
- repository =>
- {
- url => "git://git.imager.perl.org/imager-type1.git",
- web => "http://git.imager.perl.org/imager-type1.git/",
- type => "git",
- },
+ repository => "git://git.imager.perl.org/imager.git",
+ bugtracker => "http://rt.cpan.org/NoAuth/Bugs.html?Dist=Imager",
},
};
$opts{PREREQ_PM} =
@@ -93,7 +89,7 @@ if ($probe_res) {
$opts{INC} = "@inc";
if ($MM_ver > 6.06) {
- $opts{AUTHOR} = 'Tony Cook <tony@imager.perl.org>';
+ $opts{AUTHOR} = 'Tony Cook <tonyc@cpan.org>';
$opts{ABSTRACT} = 'T1Lib font driver for Imager';
}
@@ -14,7 +14,7 @@ die $Imager::ERRSTR unless $red;
ok((-d "testout" or mkdir "testout"), "make output directory");
-init_log("testout/t20oo.log", 1);
+Imager::init_log("testout/t20oo.log", 1);
my $img=Imager->new(xsize=>300, ysize=>100) or die "$Imager::ERRSTR\n";
@@ -54,12 +54,8 @@ else {
resources =>
{
homepage => "http://imager.perl.org/",
- repository =>
- {
- url => "http://imager.perl.org/svn/trunk/Imager/TIFF",
- web => "http://imager.perl.org/svnweb/public/browse/trunk/Imager/TIFF",
- type => "svn",
- },
+ repository => "git://git.imager.perl.org/imager.git",
+ bugtracker => "http://rt.cpan.org/NoAuth/Bugs.html?Dist=Imager",
},
};
$opts{PREREQ_PM} =
@@ -92,7 +88,7 @@ if ($probe_res) {
$opts{INC} = "@inc";
if ($MM_ver > 6.06) {
- $opts{AUTHOR} = 'Tony Cook <tony@imager.perl.org>';
+ $opts{AUTHOR} = 'Tony Cook <tonyc@cpan.org>';
$opts{ABSTRACT} = 'TIFF image file support for Imager';
}
@@ -0,0 +1,9 @@
+Imager::File::TIFF provides TIFF file format support for Imager.
+
+It requires libtiff to be installed.
+
+This is currently shipped as part of Imager, but Imager may install
+with out installing Imager::File::TIFF, so if you need TIFF support,
+add a dependency on Imager::File::TIFF.
+
+Makefile.PL will reject libtiff 3.9.0 due to a bug in that release.
\ No newline at end of file
@@ -4,7 +4,7 @@ use Imager;
use vars qw($VERSION @ISA);
BEGIN {
- $VERSION = "0.78";
+ $VERSION = "0.79";
eval {
require XSLoader;
@@ -131,7 +131,7 @@ Imager's TIFF support is documented in L<Imager::Files>.
=head1 AUTHOR
-Tony Cook <tony@imager.perl.org>
+Tony Cook <tonyc@cpan.org>
=head1 SEE ALSO
@@ -2550,7 +2550,7 @@ myTIFFIsCODECConfigured(uint16 scheme) {
=head1 AUTHOR
-Arnar M. Hrafnkelsson <addi@umich.edu>, Tony Cook <tony@imager.perl.org>
+Arnar M. Hrafnkelsson <addi@umich.edu>, Tony Cook <tonyc@cpan.org>
=head1 SEE ALSO
@@ -54,12 +54,8 @@ else {
resources =>
{
homepage => "http://imager.perl.org/",
- repository =>
- {
- url => "http://imager.perl.org/svn/trunk/Imager/W32",
- web => "http://imager.perl.org/svnweb/public/browse/trunk/Imager/W32",
- type => "svn",
- },
+ repository => "git://git.imager.perl.org/imager.git",
+ bugtracker => "http://rt.cpan.org/NoAuth/Bugs.html?Dist=Imager",
},
};
$opts{PREREQ_PM} =
@@ -92,7 +88,7 @@ if ($probe_res) {
$opts{INC} = "@inc";
if ($MM_ver > 6.06) {
- $opts{AUTHOR} = 'Tony Cook <tony@imager.perl.org>';
+ $opts{AUTHOR} = 'Tony Cook <tonyc@cpan.org>';
$opts{ABSTRACT} = 'Win32 font file support for Imager';
}
@@ -0,0 +1,9 @@
+Imager::Font::W32 provides font support to Imager via the Win32 GDI
+API functions..
+
+It requires Win32 header files and libraries to be available.
+
+This is currently shipped as part of Imager, but may not be installed
+as part of Imager if headers or libraries aren't found at build time.,
+if your module or application requires Win32 font support support then
+add Imager::Font::W32 as a prerequisite.
@@ -5,7 +5,7 @@ use vars qw($VERSION @ISA);
@ISA = qw(Imager::Font);
BEGIN {
- $VERSION = "0.78";
+ $VERSION = "0.79";
eval {
require XSLoader;
@@ -85,7 +85,7 @@ renamed it.
=head1 AUTHOR
-Tony Cook <tony@imager.perl.org>
+Tony Cook <tonyc@cpan.org>
=head1 SEE ALSO
@@ -55,7 +55,7 @@ int i_wf_bbox(const char *face, int size, const char *text, int length, int *bbo
MAT2 mat;
int ascent, descent, max_ascent = -size, min_descent = size;
const char *workp;
- int work_len;
+ size_t work_len;
int got_first_ch = 0;
unsigned long first_ch, last_ch;
@@ -79,6 +79,10 @@ for my $file (@files) {
open OUT, "> $outname"
or die "Cannot open $outname: $!";
+# I keep this file in git and as part of the dist, make sure newlines
+# don't mess me up
+binmode OUT;
+
print OUT <<'EOS';
Do not edit this file, it is generated automatically by apidocs.perl
from Imager's source files.
@@ -162,7 +166,7 @@ print OUT <<'EOS';
=head1 AUTHOR
-Tony Cook <tony@imager.perl.org>
+Tony Cook <tonyc@cpan.org>
=head1 SEE ALSO
@@ -353,7 +353,7 @@ i_int_hlines_fill_fill(i_img *im, i_int_hlines *hlines, i_fill_t *fill) {
=head1 AUTHOR
-Tony Cook <tony@imager.perl.org>
+Tony Cook <tonyc@cpan.org>
=head1 REVISION
@@ -39,17 +39,6 @@ Some of these functions are internal.
/* Hack around an obscure linker bug on solaris - probably due to builtin gcc thingies */
static void fake(void) { ceil(1); }
-static int i_ppix_d(i_img *im, int x, int y, const i_color *val);
-static int i_gpix_d(i_img *im, int x, int y, i_color *val);
-static int i_glin_d(i_img *im, int l, int r, int y, i_color *vals);
-static int i_plin_d(i_img *im, int l, int r, int y, const i_color *vals);
-static int i_ppixf_d(i_img *im, int x, int y, const i_fcolor *val);
-static int i_gpixf_d(i_img *im, int x, int y, i_fcolor *val);
-static int i_glinf_d(i_img *im, int l, int r, int y, i_fcolor *vals);
-static int i_plinf_d(i_img *im, int l, int r, int y, const i_fcolor *vals);
-static int i_gsamp_d(i_img *im, int l, int r, int y, i_sample_t *samps, const int *chans, int chan_count);
-static int i_gsampf_d(i_img *im, int l, int r, int y, i_fsample_t *samps, const int *chans, int chan_count);
-
/*
=item i_img_alloc()
=category Image Implementation
@@ -242,213 +231,6 @@ void i_fcolor_destroy(i_fcolor *cl) {
myfree(cl);
}
-/*
-=item IIM_base_8bit_direct (static)
-
-A static i_img object used to initialize direct 8-bit per sample images.
-
-=cut
-*/
-static i_img IIM_base_8bit_direct =
-{
- 0, /* channels set */
- 0, 0, 0, /* xsize, ysize, bytes */
- ~0U, /* ch_mask */
- i_8_bits, /* bits */
- i_direct_type, /* type */
- 0, /* virtual */
- NULL, /* idata */
- { 0, 0, NULL }, /* tags */
- NULL, /* ext_data */
-
- i_ppix_d, /* i_f_ppix */
- i_ppixf_d, /* i_f_ppixf */
- i_plin_d, /* i_f_plin */
- i_plinf_d, /* i_f_plinf */
- i_gpix_d, /* i_f_gpix */
- i_gpixf_d, /* i_f_gpixf */
- i_glin_d, /* i_f_glin */
- i_glinf_d, /* i_f_glinf */
- i_gsamp_d, /* i_f_gsamp */
- i_gsampf_d, /* i_f_gsampf */
-
- NULL, /* i_f_gpal */
- NULL, /* i_f_ppal */
- NULL, /* i_f_addcolors */
- NULL, /* i_f_getcolors */
- NULL, /* i_f_colorcount */
- NULL, /* i_f_maxcolors */
- NULL, /* i_f_findcolor */
- NULL, /* i_f_setcolors */
-
- NULL, /* i_f_destroy */
-
- i_gsamp_bits_fb,
- NULL, /* i_f_psamp_bits */
-};
-
-/*static void set_8bit_direct(i_img *im) {
- im->i_f_ppix = i_ppix_d;
- im->i_f_ppixf = i_ppixf_d;
- im->i_f_plin = i_plin_d;
- im->i_f_plinf = i_plinf_d;
- im->i_f_gpix = i_gpix_d;
- im->i_f_gpixf = i_gpixf_d;
- im->i_f_glin = i_glin_d;
- im->i_f_glinf = i_glinf_d;
- im->i_f_gpal = NULL;
- im->i_f_ppal = NULL;
- im->i_f_addcolor = NULL;
- im->i_f_getcolor = NULL;
- im->i_f_colorcount = NULL;
- im->i_f_findcolor = NULL;
- }*/
-
-/*
-=item IIM_new(x, y, ch)
-
-=item i_img_8_new(x, y, ch)
-
-=category Image creation/destruction
-
-=synopsis i_img *img = i_img_8_new(width, height, channels);
-
-Creates a new image object I<x> pixels wide, and I<y> pixels high with
-I<ch> channels.
-
-=cut
-*/
-
-
-i_img *
-IIM_new(int x,int y,int ch) {
- i_img *im;
- mm_log((1,"IIM_new(x %d,y %d,ch %d)\n",x,y,ch));
-
- im=i_img_empty_ch(NULL,x,y,ch);
-
- mm_log((1,"(%p) <- IIM_new\n",im));
- return im;
-}
-
-
-void
-IIM_DESTROY(i_img *im) {
- mm_log((1,"IIM_DESTROY(im* %p)\n",im));
- i_img_destroy(im);
- /* myfree(cl); */
-}
-
-/*
-=item i_img_new()
-
-Create new image reference - notice that this isn't an object yet and
-this should be fixed asap.
-
-=cut
-*/
-
-
-i_img *
-i_img_new() {
- i_img *im;
-
- mm_log((1,"i_img_struct()\n"));
-
- im = i_img_alloc();
-
- *im = IIM_base_8bit_direct;
- im->xsize=0;
- im->ysize=0;
- im->channels=3;
- im->ch_mask=MAXINT;
- im->bytes=0;
- im->idata=NULL;
-
- i_img_init(im);
-
- mm_log((1,"(%p) <- i_img_struct\n",im));
- return im;
-}
-
-/*
-=item i_img_empty(im, x, y)
-
-Re-new image reference (assumes 3 channels)
-
- im - Image pointer
- x - xsize of destination image
- y - ysize of destination image
-
-**FIXME** what happens if a live image is passed in here?
-
-Should this just call i_img_empty_ch()?
-
-=cut
-*/
-
-i_img *
-i_img_empty(i_img *im,int x,int y) {
- mm_log((1,"i_img_empty(*im %p, x %d, y %d)\n",im, x, y));
- return i_img_empty_ch(im, x, y, 3);
-}
-
-/*
-=item i_img_empty_ch(im, x, y, ch)
-
-Re-new image reference
-
- im - Image pointer
- x - xsize of destination image
- y - ysize of destination image
- ch - number of channels
-
-=cut
-*/
-
-i_img *
-i_img_empty_ch(i_img *im,int x,int y,int ch) {
- int bytes;
-
- mm_log((1,"i_img_empty_ch(*im %p, x %d, y %d, ch %d)\n", im, x, y, ch));
-
- if (x < 1 || y < 1) {
- i_push_error(0, "Image sizes must be positive");
- return NULL;
- }
- if (ch < 1 || ch > MAXCHANNELS) {
- i_push_errorf(0, "channels must be between 1 and %d", MAXCHANNELS);
- return NULL;
- }
- /* check this multiplication doesn't overflow */
- bytes = x*y*ch;
- if (bytes / y / ch != x) {
- i_push_errorf(0, "integer overflow calculating image allocation");
- return NULL;
- }
-
- if (im == NULL)
- im = i_img_alloc();
-
- memcpy(im, &IIM_base_8bit_direct, sizeof(i_img));
- i_tags_new(&im->tags);
- im->xsize = x;
- im->ysize = y;
- im->channels = ch;
- im->ch_mask = MAXINT;
- im->bytes=bytes;
- if ( (im->idata=mymalloc(im->bytes)) == NULL)
- i_fatal(2,"malloc() error\n");
- memset(im->idata,0,(size_t)im->bytes);
-
- im->ext_data = NULL;
-
- i_img_init(im);
-
- mm_log((1,"(%p) <- i_img_empty_ch\n",im));
- return im;
-}
-
/*
=item i_img_exorcise(im)
@@ -471,10 +253,6 @@ i_img_exorcise(i_img *im) {
im->ysize = 0;
im->channels = 0;
- im->i_f_ppix=i_ppix_d;
- im->i_f_gpix=i_gpix_d;
- im->i_f_plin=i_plin_d;
- im->i_f_glin=i_glin_d;
im->ext_data=NULL;
}
@@ -1414,388 +1192,6 @@ i_get_anonymous_color_histo(i_img *im, unsigned int **col_usage, int maxc) {
/*
=back
-=head2 8-bit per sample image internal functions
-
-These are the functions installed in an 8-bit per sample image.
-
-=over
-
-=item i_ppix_d(im, x, y, col)
-
-Internal function.
-
-This is the function kept in the i_f_ppix member of an i_img object.
-It does a normal store of a pixel into the image with range checking.
-
-Returns 0 if the pixel could be set, -1 otherwise.
-
-=cut
-*/
-static
-int
-i_ppix_d(i_img *im, int x, int y, const i_color *val) {
- int ch;
-
- if ( x>-1 && x<im->xsize && y>-1 && y<im->ysize ) {
- for(ch=0;ch<im->channels;ch++)
- if (im->ch_mask&(1<<ch))
- im->idata[(x+y*im->xsize)*im->channels+ch]=val->channel[ch];
- return 0;
- }
- return -1; /* error was clipped */
-}
-
-/*
-=item i_gpix_d(im, x, y, &col)
-
-Internal function.
-
-This is the function kept in the i_f_gpix member of an i_img object.
-It does normal retrieval of a pixel from the image with range checking.
-
-Returns 0 if the pixel could be set, -1 otherwise.
-
-=cut
-*/
-static
-int
-i_gpix_d(i_img *im, int x, int y, i_color *val) {
- int ch;
- if (x>-1 && x<im->xsize && y>-1 && y<im->ysize) {
- for(ch=0;ch<im->channels;ch++)
- val->channel[ch]=im->idata[(x+y*im->xsize)*im->channels+ch];
- return 0;
- }
- for(ch=0;ch<im->channels;ch++) val->channel[ch] = 0;
- return -1; /* error was cliped */
-}
-
-/*
-=item i_glin_d(im, l, r, y, vals)
-
-Reads a line of data from the image, storing the pixels at vals.
-
-The line runs from (l,y) inclusive to (r,y) non-inclusive
-
-vals should point at space for (r-l) pixels.
-
-l should never be less than zero (to avoid confusion about where to
-put the pixels in vals).
-
-Returns the number of pixels copied (eg. if r, l or y is out of range)
-
-=cut
-*/
-static
-int
-i_glin_d(i_img *im, int l, int r, int y, i_color *vals) {
- int ch, count, i;
- unsigned char *data;
- if (y >=0 && y < im->ysize && l < im->xsize && l >= 0) {
- if (r > im->xsize)
- r = im->xsize;
- data = im->idata + (l+y*im->xsize) * im->channels;
- count = r - l;
- for (i = 0; i < count; ++i) {
- for (ch = 0; ch < im->channels; ++ch)
- vals[i].channel[ch] = *data++;
- }
- return count;
- }
- else {
- return 0;
- }
-}
-
-/*
-=item i_plin_d(im, l, r, y, vals)
-
-Writes a line of data into the image, using the pixels at vals.
-
-The line runs from (l,y) inclusive to (r,y) non-inclusive
-
-vals should point at (r-l) pixels.
-
-l should never be less than zero (to avoid confusion about where to
-get the pixels in vals).
-
-Returns the number of pixels copied (eg. if r, l or y is out of range)
-
-=cut
-*/
-static
-int
-i_plin_d(i_img *im, int l, int r, int y, const i_color *vals) {
- int ch, count, i;
- unsigned char *data;
- if (y >=0 && y < im->ysize && l < im->xsize && l >= 0) {
- if (r > im->xsize)
- r = im->xsize;
- data = im->idata + (l+y*im->xsize) * im->channels;
- count = r - l;
- for (i = 0; i < count; ++i) {
- for (ch = 0; ch < im->channels; ++ch) {
- if (im->ch_mask & (1 << ch))
- *data = vals[i].channel[ch];
- ++data;
- }
- }
- return count;
- }
- else {
- return 0;
- }
-}
-
-/*
-=item i_ppixf_d(im, x, y, val)
-
-=cut
-*/
-static
-int
-i_ppixf_d(i_img *im, int x, int y, const i_fcolor *val) {
- int ch;
-
- if ( x>-1 && x<im->xsize && y>-1 && y<im->ysize ) {
- for(ch=0;ch<im->channels;ch++)
- if (im->ch_mask&(1<<ch)) {
- im->idata[(x+y*im->xsize)*im->channels+ch] =
- SampleFTo8(val->channel[ch]);
- }
- return 0;
- }
- return -1; /* error was clipped */
-}
-
-/*
-=item i_gpixf_d(im, x, y, val)
-
-=cut
-*/
-static
-int
-i_gpixf_d(i_img *im, int x, int y, i_fcolor *val) {
- int ch;
- if (x>-1 && x<im->xsize && y>-1 && y<im->ysize) {
- for(ch=0;ch<im->channels;ch++) {
- val->channel[ch] =
- Sample8ToF(im->idata[(x+y*im->xsize)*im->channels+ch]);
- }
- return 0;
- }
- return -1; /* error was cliped */
-}
-
-/*
-=item i_glinf_d(im, l, r, y, vals)
-
-Reads a line of data from the image, storing the pixels at vals.
-
-The line runs from (l,y) inclusive to (r,y) non-inclusive
-
-vals should point at space for (r-l) pixels.
-
-l should never be less than zero (to avoid confusion about where to
-put the pixels in vals).
-
-Returns the number of pixels copied (eg. if r, l or y is out of range)
-
-=cut
-*/
-static
-int
-i_glinf_d(i_img *im, int l, int r, int y, i_fcolor *vals) {
- int ch, count, i;
- unsigned char *data;
- if (y >=0 && y < im->ysize && l < im->xsize && l >= 0) {
- if (r > im->xsize)
- r = im->xsize;
- data = im->idata + (l+y*im->xsize) * im->channels;
- count = r - l;
- for (i = 0; i < count; ++i) {
- for (ch = 0; ch < im->channels; ++ch)
- vals[i].channel[ch] = Sample8ToF(*data++);
- }
- return count;
- }
- else {
- return 0;
- }
-}
-
-/*
-=item i_plinf_d(im, l, r, y, vals)
-
-Writes a line of data into the image, using the pixels at vals.
-
-The line runs from (l,y) inclusive to (r,y) non-inclusive
-
-vals should point at (r-l) pixels.
-
-l should never be less than zero (to avoid confusion about where to
-get the pixels in vals).
-
-Returns the number of pixels copied (eg. if r, l or y is out of range)
-
-=cut
-*/
-static
-int
-i_plinf_d(i_img *im, int l, int r, int y, const i_fcolor *vals) {
- int ch, count, i;
- unsigned char *data;
- if (y >=0 && y < im->ysize && l < im->xsize && l >= 0) {
- if (r > im->xsize)
- r = im->xsize;
- data = im->idata + (l+y*im->xsize) * im->channels;
- count = r - l;
- for (i = 0; i < count; ++i) {
- for (ch = 0; ch < im->channels; ++ch) {
- if (im->ch_mask & (1 << ch))
- *data = SampleFTo8(vals[i].channel[ch]);
- ++data;
- }
- }
- return count;
- }
- else {
- return 0;
- }
-}
-
-/*
-=item i_gsamp_d(i_img *im, int l, int r, int y, i_sample_t *samps, int *chans, int chan_count)
-
-Reads sample values from im for the horizontal line (l, y) to (r-1,y)
-for the channels specified by chans, an array of int with chan_count
-elements.
-
-Returns the number of samples read (which should be (r-l) * bits_set(chan_mask)
-
-=cut
-*/
-static
-int
-i_gsamp_d(i_img *im, int l, int r, int y, i_sample_t *samps,
- const int *chans, int chan_count) {
- int ch, count, i, w;
- unsigned char *data;
-
- if (y >=0 && y < im->ysize && l < im->xsize && l >= 0) {
- if (r > im->xsize)
- r = im->xsize;
- data = im->idata + (l+y*im->xsize) * im->channels;
- w = r - l;
- count = 0;
-
- if (chans) {
- /* make sure we have good channel numbers */
- for (ch = 0; ch < chan_count; ++ch) {
- if (chans[ch] < 0 || chans[ch] >= im->channels) {
- i_push_errorf(0, "No channel %d in this image", chans[ch]);
- return 0;
- }
- }
- for (i = 0; i < w; ++i) {
- for (ch = 0; ch < chan_count; ++ch) {
- *samps++ = data[chans[ch]];
- ++count;
- }
- data += im->channels;
- }
- }
- else {
- if (chan_count <= 0 || chan_count > im->channels) {
- i_push_errorf(0, "chan_count %d out of range, must be >0, <= channels",
- chan_count);
- return 0;
- }
- for (i = 0; i < w; ++i) {
- for (ch = 0; ch < chan_count; ++ch) {
- *samps++ = data[ch];
- ++count;
- }
- data += im->channels;
- }
- }
-
- return count;
- }
- else {
- return 0;
- }
-}
-
-/*
-=item i_gsampf_d(i_img *im, int l, int r, int y, i_fsample_t *samps, int *chans, int chan_count)
-
-Reads sample values from im for the horizontal line (l, y) to (r-1,y)
-for the channels specified by chan_mask, where bit 0 is the first
-channel.
-
-Returns the number of samples read (which should be (r-l) * bits_set(chan_mask)
-
-=cut
-*/
-static
-int
-i_gsampf_d(i_img *im, int l, int r, int y, i_fsample_t *samps,
- const int *chans, int chan_count) {
- int ch, count, i, w;
- unsigned char *data;
- for (ch = 0; ch < chan_count; ++ch) {
- if (chans[ch] < 0 || chans[ch] >= im->channels) {
- i_push_errorf(0, "No channel %d in this image", chans[ch]);
- }
- }
- if (y >=0 && y < im->ysize && l < im->xsize && l >= 0) {
- if (r > im->xsize)
- r = im->xsize;
- data = im->idata + (l+y*im->xsize) * im->channels;
- w = r - l;
- count = 0;
-
- if (chans) {
- /* make sure we have good channel numbers */
- for (ch = 0; ch < chan_count; ++ch) {
- if (chans[ch] < 0 || chans[ch] >= im->channels) {
- i_push_errorf(0, "No channel %d in this image", chans[ch]);
- return 0;
- }
- }
- for (i = 0; i < w; ++i) {
- for (ch = 0; ch < chan_count; ++ch) {
- *samps++ = Sample8ToF(data[chans[ch]]);
- ++count;
- }
- data += im->channels;
- }
- }
- else {
- if (chan_count <= 0 || chan_count > im->channels) {
- i_push_errorf(0, "chan_count %d out of range, must be >0, <= channels",
- chan_count);
- return 0;
- }
- for (i = 0; i < w; ++i) {
- for (ch = 0; ch < chan_count; ++ch) {
- *samps++ = Sample8ToF(data[ch]);
- ++count;
- }
- data += im->channels;
- }
- }
- return count;
- }
- else {
- return 0;
- }
-}
-
-/*
-=back
-
=head2 Image method wrappers
These functions provide i_fsample_t functions in terms of their
@@ -326,6 +326,7 @@ extern i_img *i_img_masked_new(i_img *targ, i_img *mask, int x, int y,
extern i_img *i_img_16_new(int x, int y, int ch);
extern i_img *i_img_to_rgb16(i_img *im);
extern i_img *i_img_double_new(int x, int y, int ch);
+extern i_img *i_img_to_drgb(i_img *im);
extern int i_img_is_monochrome(i_img *im, int *zero_is_white);
extern void i_get_file_background(i_img *im, i_color *bg);
@@ -114,4 +114,6 @@ i_img_dim i_maxx(i_img_dim x, i_img_dim y);
#define i_min(a, b) i_minx((a), (b))
#define i_max(a, b) i_maxx((a), (b))
+#define color_to_grey(col) ((col)->rgb.r * 0.222 + (col)->rgb.g * 0.707 + (col)->rgb.b * 0.071)
+
#endif
@@ -17,8 +17,10 @@ extern im_ext_funcs *imager_function_ext_table;
imager_function_ext_table = INT2PTR(im_ext_funcs *, SvIV(get_sv(PERL_FUNCTION_TABLE_NAME, 1))); \
if (!imager_function_ext_table) \
croak("Imager API function table not found!"); \
- if (imager_function_ext_table->version != IMAGER_API_VERSION) \
- croak("Imager API version incorrect"); \
+ if (imager_function_ext_table->version != IMAGER_API_VERSION) { \
+ croak("Imager API version incorrect loaded %d vs expected %d", \
+ imager_function_ext_table->version, IMAGER_API_VERSION); \
+ } \
if (imager_function_ext_table->level < IMAGER_MIN_API_LEVEL) \
croak("API level %d below minimum of %d", imager_function_ext_table->level, IMAGER_MIN_API_LEVEL); \
} while (0)
@@ -192,7 +194,7 @@ extern im_ext_funcs *imager_function_ext_table;
#define i_set_image_file_limits(max_width, max_height, max_bytes) \
((im_extt->f_i_set_image_file_limits)((max_width), (max_height), (max_bytes)))
-#define i_get_image_file_limits(max_width, max_height, max_bytes) \
+#define i_get_image_file_limits(pmax_width, pmax_height, pmax_bytes) \
((im_extt->f_i_get_image_file_limits)((pmax_width), (pmax_height), (pmax_bytes)))
#define i_int_check_image_file_limits(width, height, channels, sample_size) \
((im_extt->f_i_int_check_image_file_limits)((width), (height), (channels), (sample_size)))
@@ -17,7 +17,7 @@ extern im_pl_ext_funcs *imager_perl_function_ext_table;
imager_perl_function_ext_table = INT2PTR(im_pl_ext_funcs *, SvIV(get_sv(PERL_PL_FUNCTION_TABLE_NAME, 1))); \
if (!imager_perl_function_ext_table) \
croak("Imager Perl API function table not found!"); \
- if (imager_perl_function_ext_table->version != IMAGER_API_VERSION) \
+ if (imager_perl_function_ext_table->version != IMAGER_PL_API_VERSION) \
croak("Imager Perl API version incorrect"); \
if (imager_perl_function_ext_table->level < IMAGER_MIN_PL_API_LEVEL) \
croak("perl API level %d below minimum of %d", imager_perl_function_ext_table->level, IMAGER_MIN_PL_API_LEVEL); \
@@ -0,0 +1,616 @@
+#include "imager.h"
+#include "imageri.h"
+
+static int i_ppix_d(i_img *im, int x, int y, const i_color *val);
+static int i_gpix_d(i_img *im, int x, int y, i_color *val);
+static int i_glin_d(i_img *im, int l, int r, int y, i_color *vals);
+static int i_plin_d(i_img *im, int l, int r, int y, const i_color *vals);
+static int i_ppixf_d(i_img *im, int x, int y, const i_fcolor *val);
+static int i_gpixf_d(i_img *im, int x, int y, i_fcolor *val);
+static int i_glinf_d(i_img *im, int l, int r, int y, i_fcolor *vals);
+static int i_plinf_d(i_img *im, int l, int r, int y, const i_fcolor *vals);
+static int i_gsamp_d(i_img *im, int l, int r, int y, i_sample_t *samps, const int *chans, int chan_count);
+static int i_gsampf_d(i_img *im, int l, int r, int y, i_fsample_t *samps, const int *chans, int chan_count);
+
+/*
+=item IIM_base_8bit_direct (static)
+
+A static i_img object used to initialize direct 8-bit per sample images.
+
+=cut
+*/
+static i_img IIM_base_8bit_direct =
+{
+ 0, /* channels set */
+ 0, 0, 0, /* xsize, ysize, bytes */
+ ~0U, /* ch_mask */
+ i_8_bits, /* bits */
+ i_direct_type, /* type */
+ 0, /* virtual */
+ NULL, /* idata */
+ { 0, 0, NULL }, /* tags */
+ NULL, /* ext_data */
+
+ i_ppix_d, /* i_f_ppix */
+ i_ppixf_d, /* i_f_ppixf */
+ i_plin_d, /* i_f_plin */
+ i_plinf_d, /* i_f_plinf */
+ i_gpix_d, /* i_f_gpix */
+ i_gpixf_d, /* i_f_gpixf */
+ i_glin_d, /* i_f_glin */
+ i_glinf_d, /* i_f_glinf */
+ i_gsamp_d, /* i_f_gsamp */
+ i_gsampf_d, /* i_f_gsampf */
+
+ NULL, /* i_f_gpal */
+ NULL, /* i_f_ppal */
+ NULL, /* i_f_addcolors */
+ NULL, /* i_f_getcolors */
+ NULL, /* i_f_colorcount */
+ NULL, /* i_f_maxcolors */
+ NULL, /* i_f_findcolor */
+ NULL, /* i_f_setcolors */
+
+ NULL, /* i_f_destroy */
+
+ i_gsamp_bits_fb,
+ NULL, /* i_f_psamp_bits */
+};
+
+/*static void set_8bit_direct(i_img *im) {
+ im->i_f_ppix = i_ppix_d;
+ im->i_f_ppixf = i_ppixf_d;
+ im->i_f_plin = i_plin_d;
+ im->i_f_plinf = i_plinf_d;
+ im->i_f_gpix = i_gpix_d;
+ im->i_f_gpixf = i_gpixf_d;
+ im->i_f_glin = i_glin_d;
+ im->i_f_glinf = i_glinf_d;
+ im->i_f_gpal = NULL;
+ im->i_f_ppal = NULL;
+ im->i_f_addcolor = NULL;
+ im->i_f_getcolor = NULL;
+ im->i_f_colorcount = NULL;
+ im->i_f_findcolor = NULL;
+ }*/
+
+/*
+=item IIM_new(x, y, ch)
+
+=item i_img_8_new(x, y, ch)
+
+=category Image creation/destruction
+
+=synopsis i_img *img = i_img_8_new(width, height, channels);
+
+Creates a new image object I<x> pixels wide, and I<y> pixels high with
+I<ch> channels.
+
+=cut
+*/
+
+
+i_img *
+IIM_new(int x,int y,int ch) {
+ i_img *im;
+ mm_log((1,"IIM_new(x %d,y %d,ch %d)\n",x,y,ch));
+
+ im=i_img_empty_ch(NULL,x,y,ch);
+
+ mm_log((1,"(%p) <- IIM_new\n",im));
+ return im;
+}
+
+
+void
+IIM_DESTROY(i_img *im) {
+ mm_log((1,"IIM_DESTROY(im* %p)\n",im));
+ i_img_destroy(im);
+ /* myfree(cl); */
+}
+
+/*
+=item i_img_new()
+
+Create new image reference - notice that this isn't an object yet and
+this should be fixed asap.
+
+=cut
+*/
+
+
+i_img *
+i_img_new() {
+ i_img *im;
+
+ mm_log((1,"i_img_struct()\n"));
+
+ im = i_img_alloc();
+
+ *im = IIM_base_8bit_direct;
+ im->xsize=0;
+ im->ysize=0;
+ im->channels=3;
+ im->ch_mask=MAXINT;
+ im->bytes=0;
+ im->idata=NULL;
+
+ i_img_init(im);
+
+ mm_log((1,"(%p) <- i_img_struct\n",im));
+ return im;
+}
+
+/*
+=item i_img_empty(im, x, y)
+
+Re-new image reference (assumes 3 channels)
+
+ im - Image pointer
+ x - xsize of destination image
+ y - ysize of destination image
+
+**FIXME** what happens if a live image is passed in here?
+
+Should this just call i_img_empty_ch()?
+
+=cut
+*/
+
+i_img *
+i_img_empty(i_img *im,int x,int y) {
+ mm_log((1,"i_img_empty(*im %p, x %d, y %d)\n",im, x, y));
+ return i_img_empty_ch(im, x, y, 3);
+}
+
+/*
+=item i_img_empty_ch(im, x, y, ch)
+
+Re-new image reference
+
+ im - Image pointer
+ x - xsize of destination image
+ y - ysize of destination image
+ ch - number of channels
+
+=cut
+*/
+
+i_img *
+i_img_empty_ch(i_img *im,int x,int y,int ch) {
+ int bytes;
+
+ mm_log((1,"i_img_empty_ch(*im %p, x %d, y %d, ch %d)\n", im, x, y, ch));
+
+ if (x < 1 || y < 1) {
+ i_push_error(0, "Image sizes must be positive");
+ return NULL;
+ }
+ if (ch < 1 || ch > MAXCHANNELS) {
+ i_push_errorf(0, "channels must be between 1 and %d", MAXCHANNELS);
+ return NULL;
+ }
+ /* check this multiplication doesn't overflow */
+ bytes = x*y*ch;
+ if (bytes / y / ch != x) {
+ i_push_errorf(0, "integer overflow calculating image allocation");
+ return NULL;
+ }
+
+ if (im == NULL)
+ im = i_img_alloc();
+
+ memcpy(im, &IIM_base_8bit_direct, sizeof(i_img));
+ i_tags_new(&im->tags);
+ im->xsize = x;
+ im->ysize = y;
+ im->channels = ch;
+ im->ch_mask = MAXINT;
+ im->bytes=bytes;
+ if ( (im->idata=mymalloc(im->bytes)) == NULL)
+ i_fatal(2,"malloc() error\n");
+ memset(im->idata,0,(size_t)im->bytes);
+
+ im->ext_data = NULL;
+
+ i_img_init(im);
+
+ mm_log((1,"(%p) <- i_img_empty_ch\n",im));
+ return im;
+}
+
+/*
+=head2 8-bit per sample image internal functions
+
+These are the functions installed in an 8-bit per sample image.
+
+=over
+
+=item i_ppix_d(im, x, y, col)
+
+Internal function.
+
+This is the function kept in the i_f_ppix member of an i_img object.
+It does a normal store of a pixel into the image with range checking.
+
+Returns 0 if the pixel could be set, -1 otherwise.
+
+=cut
+*/
+static
+int
+i_ppix_d(i_img *im, int x, int y, const i_color *val) {
+ int ch;
+
+ if ( x>-1 && x<im->xsize && y>-1 && y<im->ysize ) {
+ for(ch=0;ch<im->channels;ch++)
+ if (im->ch_mask&(1<<ch))
+ im->idata[(x+y*im->xsize)*im->channels+ch]=val->channel[ch];
+ return 0;
+ }
+ return -1; /* error was clipped */
+}
+
+/*
+=item i_gpix_d(im, x, y, &col)
+
+Internal function.
+
+This is the function kept in the i_f_gpix member of an i_img object.
+It does normal retrieval of a pixel from the image with range checking.
+
+Returns 0 if the pixel could be set, -1 otherwise.
+
+=cut
+*/
+static
+int
+i_gpix_d(i_img *im, int x, int y, i_color *val) {
+ int ch;
+ if (x>-1 && x<im->xsize && y>-1 && y<im->ysize) {
+ for(ch=0;ch<im->channels;ch++)
+ val->channel[ch]=im->idata[(x+y*im->xsize)*im->channels+ch];
+ return 0;
+ }
+ for(ch=0;ch<im->channels;ch++) val->channel[ch] = 0;
+ return -1; /* error was cliped */
+}
+
+/*
+=item i_glin_d(im, l, r, y, vals)
+
+Reads a line of data from the image, storing the pixels at vals.
+
+The line runs from (l,y) inclusive to (r,y) non-inclusive
+
+vals should point at space for (r-l) pixels.
+
+l should never be less than zero (to avoid confusion about where to
+put the pixels in vals).
+
+Returns the number of pixels copied (eg. if r, l or y is out of range)
+
+=cut
+*/
+static
+int
+i_glin_d(i_img *im, int l, int r, int y, i_color *vals) {
+ int ch, count, i;
+ unsigned char *data;
+ if (y >=0 && y < im->ysize && l < im->xsize && l >= 0) {
+ if (r > im->xsize)
+ r = im->xsize;
+ data = im->idata + (l+y*im->xsize) * im->channels;
+ count = r - l;
+ for (i = 0; i < count; ++i) {
+ for (ch = 0; ch < im->channels; ++ch)
+ vals[i].channel[ch] = *data++;
+ }
+ return count;
+ }
+ else {
+ return 0;
+ }
+}
+
+/*
+=item i_plin_d(im, l, r, y, vals)
+
+Writes a line of data into the image, using the pixels at vals.
+
+The line runs from (l,y) inclusive to (r,y) non-inclusive
+
+vals should point at (r-l) pixels.
+
+l should never be less than zero (to avoid confusion about where to
+get the pixels in vals).
+
+Returns the number of pixels copied (eg. if r, l or y is out of range)
+
+=cut
+*/
+static
+int
+i_plin_d(i_img *im, int l, int r, int y, const i_color *vals) {
+ int ch, count, i;
+ unsigned char *data;
+ if (y >=0 && y < im->ysize && l < im->xsize && l >= 0) {
+ if (r > im->xsize)
+ r = im->xsize;
+ data = im->idata + (l+y*im->xsize) * im->channels;
+ count = r - l;
+ for (i = 0; i < count; ++i) {
+ for (ch = 0; ch < im->channels; ++ch) {
+ if (im->ch_mask & (1 << ch))
+ *data = vals[i].channel[ch];
+ ++data;
+ }
+ }
+ return count;
+ }
+ else {
+ return 0;
+ }
+}
+
+/*
+=item i_ppixf_d(im, x, y, val)
+
+=cut
+*/
+static
+int
+i_ppixf_d(i_img *im, int x, int y, const i_fcolor *val) {
+ int ch;
+
+ if ( x>-1 && x<im->xsize && y>-1 && y<im->ysize ) {
+ for(ch=0;ch<im->channels;ch++)
+ if (im->ch_mask&(1<<ch)) {
+ im->idata[(x+y*im->xsize)*im->channels+ch] =
+ SampleFTo8(val->channel[ch]);
+ }
+ return 0;
+ }
+ return -1; /* error was clipped */
+}
+
+/*
+=item i_gpixf_d(im, x, y, val)
+
+=cut
+*/
+static
+int
+i_gpixf_d(i_img *im, int x, int y, i_fcolor *val) {
+ int ch;
+ if (x>-1 && x<im->xsize && y>-1 && y<im->ysize) {
+ for(ch=0;ch<im->channels;ch++) {
+ val->channel[ch] =
+ Sample8ToF(im->idata[(x+y*im->xsize)*im->channels+ch]);
+ }
+ return 0;
+ }
+ return -1; /* error was cliped */
+}
+
+/*
+=item i_glinf_d(im, l, r, y, vals)
+
+Reads a line of data from the image, storing the pixels at vals.
+
+The line runs from (l,y) inclusive to (r,y) non-inclusive
+
+vals should point at space for (r-l) pixels.
+
+l should never be less than zero (to avoid confusion about where to
+put the pixels in vals).
+
+Returns the number of pixels copied (eg. if r, l or y is out of range)
+
+=cut
+*/
+static
+int
+i_glinf_d(i_img *im, int l, int r, int y, i_fcolor *vals) {
+ int ch, count, i;
+ unsigned char *data;
+ if (y >=0 && y < im->ysize && l < im->xsize && l >= 0) {
+ if (r > im->xsize)
+ r = im->xsize;
+ data = im->idata + (l+y*im->xsize) * im->channels;
+ count = r - l;
+ for (i = 0; i < count; ++i) {
+ for (ch = 0; ch < im->channels; ++ch)
+ vals[i].channel[ch] = Sample8ToF(*data++);
+ }
+ return count;
+ }
+ else {
+ return 0;
+ }
+}
+
+/*
+=item i_plinf_d(im, l, r, y, vals)
+
+Writes a line of data into the image, using the pixels at vals.
+
+The line runs from (l,y) inclusive to (r,y) non-inclusive
+
+vals should point at (r-l) pixels.
+
+l should never be less than zero (to avoid confusion about where to
+get the pixels in vals).
+
+Returns the number of pixels copied (eg. if r, l or y is out of range)
+
+=cut
+*/
+static
+int
+i_plinf_d(i_img *im, int l, int r, int y, const i_fcolor *vals) {
+ int ch, count, i;
+ unsigned char *data;
+ if (y >=0 && y < im->ysize && l < im->xsize && l >= 0) {
+ if (r > im->xsize)
+ r = im->xsize;
+ data = im->idata + (l+y*im->xsize) * im->channels;
+ count = r - l;
+ for (i = 0; i < count; ++i) {
+ for (ch = 0; ch < im->channels; ++ch) {
+ if (im->ch_mask & (1 << ch))
+ *data = SampleFTo8(vals[i].channel[ch]);
+ ++data;
+ }
+ }
+ return count;
+ }
+ else {
+ return 0;
+ }
+}
+
+/*
+=item i_gsamp_d(i_img *im, int l, int r, int y, i_sample_t *samps, int *chans, int chan_count)
+
+Reads sample values from im for the horizontal line (l, y) to (r-1,y)
+for the channels specified by chans, an array of int with chan_count
+elements.
+
+Returns the number of samples read (which should be (r-l) * bits_set(chan_mask)
+
+=cut
+*/
+static
+int
+i_gsamp_d(i_img *im, int l, int r, int y, i_sample_t *samps,
+ const int *chans, int chan_count) {
+ int ch, count, i, w;
+ unsigned char *data;
+
+ if (y >=0 && y < im->ysize && l < im->xsize && l >= 0) {
+ if (r > im->xsize)
+ r = im->xsize;
+ data = im->idata + (l+y*im->xsize) * im->channels;
+ w = r - l;
+ count = 0;
+
+ if (chans) {
+ /* make sure we have good channel numbers */
+ for (ch = 0; ch < chan_count; ++ch) {
+ if (chans[ch] < 0 || chans[ch] >= im->channels) {
+ i_push_errorf(0, "No channel %d in this image", chans[ch]);
+ return 0;
+ }
+ }
+ for (i = 0; i < w; ++i) {
+ for (ch = 0; ch < chan_count; ++ch) {
+ *samps++ = data[chans[ch]];
+ ++count;
+ }
+ data += im->channels;
+ }
+ }
+ else {
+ if (chan_count <= 0 || chan_count > im->channels) {
+ i_push_errorf(0, "chan_count %d out of range, must be >0, <= channels",
+ chan_count);
+ return 0;
+ }
+ for (i = 0; i < w; ++i) {
+ for (ch = 0; ch < chan_count; ++ch) {
+ *samps++ = data[ch];
+ ++count;
+ }
+ data += im->channels;
+ }
+ }
+
+ return count;
+ }
+ else {
+ return 0;
+ }
+}
+
+/*
+=item i_gsampf_d(i_img *im, int l, int r, int y, i_fsample_t *samps, int *chans, int chan_count)
+
+Reads sample values from im for the horizontal line (l, y) to (r-1,y)
+for the channels specified by chan_mask, where bit 0 is the first
+channel.
+
+Returns the number of samples read (which should be (r-l) * bits_set(chan_mask)
+
+=cut
+*/
+static
+int
+i_gsampf_d(i_img *im, int l, int r, int y, i_fsample_t *samps,
+ const int *chans, int chan_count) {
+ int ch, count, i, w;
+ unsigned char *data;
+ for (ch = 0; ch < chan_count; ++ch) {
+ if (chans[ch] < 0 || chans[ch] >= im->channels) {
+ i_push_errorf(0, "No channel %d in this image", chans[ch]);
+ }
+ }
+ if (y >=0 && y < im->ysize && l < im->xsize && l >= 0) {
+ if (r > im->xsize)
+ r = im->xsize;
+ data = im->idata + (l+y*im->xsize) * im->channels;
+ w = r - l;
+ count = 0;
+
+ if (chans) {
+ /* make sure we have good channel numbers */
+ for (ch = 0; ch < chan_count; ++ch) {
+ if (chans[ch] < 0 || chans[ch] >= im->channels) {
+ i_push_errorf(0, "No channel %d in this image", chans[ch]);
+ return 0;
+ }
+ }
+ for (i = 0; i < w; ++i) {
+ for (ch = 0; ch < chan_count; ++ch) {
+ *samps++ = Sample8ToF(data[chans[ch]]);
+ ++count;
+ }
+ data += im->channels;
+ }
+ }
+ else {
+ if (chan_count <= 0 || chan_count > im->channels) {
+ i_push_errorf(0, "chan_count %d out of range, must be >0, <= channels",
+ chan_count);
+ return 0;
+ }
+ for (i = 0; i < w; ++i) {
+ for (ch = 0; ch < chan_count; ++ch) {
+ *samps++ = Sample8ToF(data[ch]);
+ ++count;
+ }
+ data += im->channels;
+ }
+ }
+ return count;
+ }
+ else {
+ return 0;
+ }
+}
+
+/*
+=back
+
+=head1 AUTHOR
+
+Arnar M. Hrafnkelsson <addi@umich.edu>
+
+Tony Cook <tony@develop-help.com>
+
+=head1 SEE ALSO
+
+L<Imager>
+
+=cut
+*/
@@ -399,6 +399,37 @@ static int i_gsampf_ddoub(i_img *im, int l, int r, int y, i_fsample_t *samps,
}
}
+/*
+=item i_img_to_drgb(im)
+
+=category Image creation
+
+Returns a double/sample version of the supplied image.
+
+Returns the image on success, or NULL on failure.
+
+=cut
+*/
+
+i_img *
+i_img_to_drgb(i_img *im) {
+ i_img *targ;
+ i_fcolor *line;
+ int y;
+
+ targ = i_img_double_new(im->xsize, im->ysize, im->channels);
+ if (!targ)
+ return NULL;
+ line = mymalloc(sizeof(i_fcolor) * im->xsize);
+ for (y = 0; y < im->ysize; ++y) {
+ i_glinf(im, 0, im->xsize, y, line);
+ i_plinf(targ, 0, im->xsize, y, line);
+ }
+
+ myfree(line);
+
+ return targ;
+}
/*
=back
@@ -252,7 +252,7 @@ should include Imager in your configure_requires:
=head1 AUTHOR
-Tony Cook <tony@imager.perl.org>
+Tony Cook <tonyc@cpan.org>
=head1 SEE ALSO
@@ -1003,7 +1003,7 @@ I<ch> channels.
=for comment
-From: File image.c
+From: File img8.c
=item i_img_double_new(int x, int y, int ch)
@@ -1618,7 +1618,7 @@ From: File io.c
=head1 AUTHOR
-Tony Cook <tony@imager.perl.org>
+Tony Cook <tonyc@cpan.org>
=head1 SEE ALSO
@@ -1186,7 +1186,7 @@ unified yet.
=head1 AUTHOR
-Tony Cook <tony@imager.perl.org>, Arnar M. Hrafnkelsson.
+Tony Cook <tonyc@cpan.org>, Arnar M. Hrafnkelsson.
=head1 SEE ALSO
@@ -122,7 +122,7 @@ __END__
=head1 AUTHOR
-Tony Cook <tony@imager.perl.org>
+Tony Cook <tonyc@cpan.org>
=head1 REVISION
@@ -496,26 +496,32 @@ to control output:
=over
-=item C<jpeg_density_unit>
+=item *
-The value of the density unit field in the C<JFIF> header. This is
-ignored on writing if the C<i_aspect_only> tag is non-zero.
+C<jpeg_density_unit> - The value of the density unit field in the
+C<JFIF> header. This is ignored on writing if the C<i_aspect_only>
+tag is non-zero.
The C<i_xres> and C<i_yres> tags are expressed in pixels per inch no
matter the value of this tag, they will be converted to/from the value
stored in the JPEG file.
-=item C<jpeg_density_unit_name>
+=item *
-This is set when reading a JPEG file to the name of the unit given by
-C<jpeg_density_unit>. Possible results include C<inch>,
-C<centimeter>, C<none> (the C<i_aspect_only> tag is also set reading
-these files). If the value of C<jpeg_density_unit> is unknown then
-this tag isn't set.
+C<jpeg_density_unit_name> - This is set when reading a JPEG file to
+the name of the unit given by C<jpeg_density_unit>. Possible results
+include C<inch>, C<centimeter>, C<none> (the C<i_aspect_only> tag is
+also set reading these files). If the value of C<jpeg_density_unit>
+is unknown then this tag isn't set.
-=item C<jpeg_comment>
+=item *
+
+C<jpeg_comment> - Text comment.
+
+=item *
-Text comment.
+C<jpeg_progressive> - Whether the JPEG file is a progressive
+file. (Imager 0.84)
=back
@@ -748,7 +748,7 @@ For large sample images this is scaled down to the range 0 .. 1.
=head1 AUTHOR
-Arnar M. Hrafnkelsson, Tony Cook <tony@imager.perl.org>.
+Arnar M. Hrafnkelsson, Tony Cook <tonyc@cpan.org>.
=head1 SEE ALSO
@@ -51,7 +51,7 @@ description directly to the drawing method.
=head1 AUTHOR
-Tony Cook <tony@imager.perl.org>
+Tony Cook <tonyc@cpan.org>
=cut
@@ -99,7 +99,7 @@ Returns 0 on success, -1 on failure.
=head1 AUTHOR
-Tony Cook <tony@imager.perl.org>
+Tony Cook <tonyc@cpan.org>
=head1 SEE ALSO
@@ -638,13 +638,21 @@ No parameters.
=item to_rgb16()
-You can convert a paletted image (or any image) to an 16-bit/channel
-RGB image with:
+Convert a paletted image (or any image) to a 16-bit/channel RGB image.
$rgbimg = $img->to_rgb16;
No parameters.
+=item to_rgb_double()
+
+Convert a paletted image (or any image) to an double/channel direct
+color image.
+
+ $rgbimg = $img->to_rgb_double;
+
+No parameters.
+
=item masked()
Creates a masked image. A masked image lets you create an image proxy
@@ -1039,7 +1047,8 @@ Possible values are:
=item *
-C<giflib> - the C<giflib> native quantization function is used.
+C<giflib> - this is a historical equivalent for C<closest> that also
+forces C<make_colors> to C<mediancut>.
=item *
@@ -1052,7 +1061,9 @@ closest color is chosen.
=item *
-C<errdiff> - an error diffusion dither is performed.
+C<errdiff> - an error diffusion dither is performed. If the supplied
+(or generated) palette contains only grays the source colors are
+converted to gray before error diffusion is performed.
=back
@@ -1120,9 +1131,10 @@ This function is a mess, it can take the following named parameters:
=item *
-C<log> - name of a log file to log Imager's actions to. Not all actions
-are logged, but the debugging memory allocator does log allocations
-here. Ignored if Imager has been built without logging support.
+C<log> - name of a log file to log Imager's actions to. Not all
+actions are logged, but the debugging memory allocator does log
+allocations here. Ignored if Imager has been built without logging
+support. Preferably use the open_log() method instead.
=item *
@@ -1147,6 +1159,69 @@ Example:
=back
+=head1 LOGGING METHODS
+
+Imager can open an internal log to send debugging information to.
+This log is extensively used in Imager's tests, but you're unlikely to
+use it otherwise.
+
+If Imager has been built with logging disabled, the methods fail
+quietly.
+
+=over
+
+=item open_log()
+
+Open the Imager debugging log file.
+
+=over
+
+=item *
+
+C<log> - the file name to log to. If this is undef logging information
+is sent to the standard error stream.
+
+=item *
+
+C<loglevel> the level of logging to produce. Default: 1.
+
+=back
+
+Returns a true value if the log file was opened successfully.
+
+ # send debug output to test.log
+ Imager->open_log(log => "test.log");
+
+ # send debug output to stderr
+ Imager->open_log();
+
+=item close_log()
+
+Close the Imager debugging log file and disable debug logging.
+
+No parameters.
+
+ Imager->close_log();
+
+=item log()
+
+ Imager->log($message)
+ Imager->log($message, $level)
+
+This method does not use named parameters.
+
+The default for C<$level> is 1.
+
+Send a message to the debug log.
+
+ Imager->log("My code got here!");
+
+=item is_logging()
+
+Returns a true value if logging is enabled.
+
+=back
+
=head1 REVISION
$Revision$
@@ -62,7 +62,7 @@ C<"Imager:" ":Color">.
=head1 AUTHOR
-Tony Cook <tony@imager.perl.org>
+Tony Cook <tonyc@cpan.org>
=head1 REVISION
@@ -107,7 +107,7 @@ of the image, using filled => 1 and color works at 8-bits/sample
=head1 AUTHOR
-Tony Cook <tony@imager.perl.org>
+Tony Cook <tonyc@cpan.org>
=cut
@@ -319,6 +319,6 @@ Other types, functions and values may be added in the future.
=head1 AUTHOR
-Tony Cook <tony@imager.perl.org>
+Tony Cook <tonyc@cpan.org>
=cut
@@ -963,7 +963,7 @@ L<Imager>, L<Imager::Engines>
=head1 AUTHOR
-Tony Cook <tony@imager.perl.org>, Arnar M. Hrafnkelsson
+Tony Cook <tonyc@cpan.org>, Arnar M. Hrafnkelsson
=head1 REVISION
@@ -173,7 +173,7 @@ so the complete program is:
=head1 AUTHOR
-Tony Cook <tony@imager.perl.org>
+Tony Cook <tonyc@cpan.org>
=head1 REVISION
@@ -1,6 +1,9 @@
#include "imconfig.h"
#include "log.h"
#include <stdlib.h>
+#include <errno.h>
+
+#ifdef IMAGER_LOG
#define DTBUFF 50
#define DATABUFF DTBUFF+3+10+1+5+1+1
@@ -12,14 +15,13 @@ static char date_buffer[DTBUFF];
static char data_buffer[DATABUFF];
-#ifdef IMAGER_LOG
-
/*
* Logging is active
*/
-void
+int
i_init_log(const char* name,int level) {
+ i_clear_error();
log_level = level;
if (level < 0) {
lg_file = NULL;
@@ -28,13 +30,17 @@ i_init_log(const char* name,int level) {
lg_file = stderr;
} else {
if (NULL == (lg_file = fopen(name, "w+")) ) {
- fprintf(stderr,"Cannot open file '%s'\n",name);
- exit(2);
+ i_push_errorf(errno, "Cannot open file '%s': (%d)", name, errno);
+ return 0;
}
}
}
- setvbuf(lg_file, NULL, _IONBF, BUFSIZ);
- mm_log((0,"Imager - log started (level = %d)\n", level));
+ if (lg_file) {
+ setvbuf(lg_file, NULL, _IONBF, BUFSIZ);
+ mm_log((0,"Imager - log started (level = %d)\n", level));
+ }
+
+ return lg_file != NULL;
}
void
@@ -55,17 +61,6 @@ i_fatal(int exitcode,const char *fmt, ... ) {
exit(exitcode);
}
-#else
-
-/*
- * Logging is inactive - insert dummy functions
- */
-
-void i_init_log(const char* name,int onoff) {}
-void i_fatal(int exitcode,const char *fmt, ... ) { exit(exitcode); }
-
-
-#endif
/*
=item i_loog(level, format, ...)
@@ -111,3 +106,26 @@ i_lhead(const char *file, int line) {
sprintf(data_buffer, "[%s] %10s:%-5d ", date_buffer, file, line);
}
}
+
+#else
+
+/*
+ * Logging is inactive - insert dummy functions
+ */
+
+int i_init_log(const char* name,int onoff) {
+ i_clear_error();
+ i_push_error(0, "Logging disabled");
+ return 0;
+}
+
+void i_fatal(int exitcode,const char *fmt, ... ) { exit(exitcode); }
+
+void
+i_loog(int level,const char *fmt, ... ) {
+}
+
+void
+i_lhead(const char *file, int line) { }
+
+#endif
@@ -10,10 +10,10 @@
global: creates a global variable FILE* lg_file
*/
+int i_init_log( const char *name, int onoff );
+void i_fatal ( int exitcode,const char *fmt, ... );
void i_lhead ( const char *file, int line );
-void i_init_log( const char *name, int onoff );
void i_loog(int level,const char *msg, ... );
-void i_fatal ( int exitcode,const char *fmt, ... );
/*
=item mm_log((level, format, ...))
@@ -1,4 +1,5 @@
#include "imager.h"
+#include "imageri.h"
/*
=item i_copyto(C<dest>, C<src>, C<x1>, C<y1>, C<x2>, C<y2>, C<tx>, C<ty>)
@@ -59,8 +60,6 @@ i_copyto(i_img *im, i_img *src, int x1, int y1, int x2, int y2, int tx, int ty)
#/code
}
-#define color_to_grey(col) ((col)->rgb.r * 0.222 + (col)->rgb.g * 0.707 + (col)->rgb.b * 0.071)
-
#code
void
#ifdef IM_EIGHT_BIT
@@ -955,7 +955,7 @@ i_writeppm_wiol(i_img *im, io_glue *ig) {
=head1 AUTHOR
-Arnar M. Hrafnkelsson <addi@umich.edu>, Tony Cook<tony@imager.perl.org>,
+Arnar M. Hrafnkelsson <addi@umich.edu>, Tony Cook <tonyc@cpan.org>,
Philip Gwyn <gwyn@cpan.org>.
=head1 SEE ALSO
@@ -5,10 +5,13 @@
#include "imager.h"
#include "imageri.h"
+static void makemap_webmap(i_quantize *);
static void makemap_addi(i_quantize *, i_img **imgs, int count);
static void makemap_mediancut(i_quantize *, i_img **imgs, int count);
static void makemap_mono(i_quantize *);
+static int makemap_palette(i_quantize *, i_img **imgs, int count);
+
static
void
setcol(i_color *cl,unsigned char r,unsigned char g,unsigned char b,unsigned char a) {
@@ -58,15 +61,7 @@ i_quant_makemap(i_quantize *quant, i_img **imgs, int count) {
/* use user's specified map */
break;
case mc_web_map:
- {
- int r, g, b;
- int i = 0;
- for (r = 0; r < 256; r+=0x33)
- for (g = 0; g < 256; g+=0x33)
- for (b = 0; b < 256; b += 0x33)
- setcol(quant->mc_colors+i++, r, g, b, 255);
- quant->mc_count = i;
- }
+ makemap_webmap(quant);
break;
case mc_median_cut:
@@ -223,9 +218,12 @@ eucl_d_ch(cvec* cv,i_sample_t *chans) {
+ PWR2(cv->b - chans[2]);
}
-static
-int
-ceucl_d(i_color *c1, i_color *c2) { return PWR2(c1->channel[0]-c2->channel[0])+PWR2(c1->channel[1]-c2->channel[1])+PWR2(c1->channel[2]-c2->channel[2]); }
+static int
+ceucl_d(i_color *c1, i_color *c2) {
+return PWR2(c1->channel[0]-c2->channel[0])
+ +PWR2(c1->channel[1]-c2->channel[1])
+ +PWR2(c1->channel[2]-c2->channel[2]);
+}
static const int
gray_samples[] = { 0, 0, 0 };
@@ -296,6 +294,9 @@ makemap_addi(i_quantize *quant, i_img **imgs, int count) {
mm_log((1, "makemap_addi(quant %p { mc_count=%d, mc_colors=%p }, imgs %p, count %d)\n",
quant, quant->mc_count, quant->mc_colors, imgs, count));
+
+ if (makemap_palette(quant, imgs, count))
+ return;
i_mempool_init(&mp);
@@ -443,6 +444,8 @@ makemap_addi(i_quantize *quant, i_img **imgs, int count) {
#endif
i_mempool_destroy(&mp);
+
+ mm_log((1, "makemap_addi() - %d colors\n", quant->mc_count));
}
typedef struct {
@@ -546,7 +549,11 @@ makemap_mediancut(i_quantize *quant, i_img **imgs, int count) {
this isn't terribly efficient, but it should work */
int chan_count;
- /*printf("images %d pal size %d\n", count, quant->mc_size);*/
+ mm_log((1, "makemap_mediancut(quant %p { mc_count=%d, mc_colors=%p }, imgs %p, count %d)\n",
+ quant, quant->mc_count, quant->mc_colors, imgs, count));
+
+ if (makemap_palette(quant, imgs, count))
+ return;
i_mempool_init(&mp);
@@ -701,6 +708,8 @@ makemap_mediancut(i_quantize *quant, i_img **imgs, int count) {
}
/*printf("out %d colors\n", quant->mc_count);*/
i_mempool_destroy(&mp);
+
+ mm_log((1, "makemap_mediancut() - %d colors\n", quant->mc_count));
}
static void
@@ -716,6 +725,112 @@ makemap_mono(i_quantize *quant) {
quant->mc_count = 2;
}
+static void
+makemap_webmap(i_quantize *quant) {
+ int r, g, b;
+
+ int i = 0;
+ for (r = 0; r < 256; r+=0x33)
+ for (g = 0; g < 256; g+=0x33)
+ for (b = 0; b < 256; b += 0x33)
+ setcol(quant->mc_colors+i++, r, g, b, 255);
+ quant->mc_count = i;
+}
+
+static int
+in_palette(i_color *c, i_quantize *quant, int size) {
+ int i;
+
+ for (i = 0; i < size; ++i) {
+ if (c->channel[0] == quant->mc_colors[i].channel[0]
+ && c->channel[1] == quant->mc_colors[i].channel[1]
+ && c->channel[2] == quant->mc_colors[i].channel[2]) {
+ return i;
+ }
+ }
+
+ return -1;
+}
+
+/*
+=item makemap_palette(quant, imgs, count)
+
+Tests if all the given images are paletted and have a common palette,
+if they do it builds that palette.
+
+A possible improvement might be to eliminate unused colors in the
+images palettes.
+
+=cut
+*/
+
+static int
+makemap_palette(i_quantize *quant, i_img **imgs, int count) {
+ int size = quant->mc_count;
+ int i;
+ int imgn;
+ char used[256];
+ int col_count;
+
+ mm_log((1, "makemap_palette(quant %p { mc_count=%d, mc_colors=%p }, imgs %p, count %d)\n",
+ quant, quant->mc_count, quant->mc_colors, imgs, count));
+ /* we try to build a common palette here, if we can manage that, then
+ that's the palette we use */
+ for (imgn = 0; imgn < count; ++imgn) {
+ int eliminate_unused;
+ if (imgs[imgn]->type != i_palette_type) {
+ mm_log((1, "makemap_palette() -> 0 (non-palette image)\n"));
+ return 0;
+ }
+
+ if (!i_tags_get_int(&imgs[imgn]->tags, "gif_eliminate_unused", 0,
+ &eliminate_unused)) {
+ eliminate_unused = 1;
+ }
+
+ if (eliminate_unused) {
+ i_palidx *line = mymalloc(sizeof(i_palidx) * imgs[imgn]->xsize);
+ int x, y;
+ memset(used, 0, sizeof(used));
+
+ for (y = 0; y < imgs[imgn]->ysize; ++y) {
+ i_gpal(imgs[imgn], 0, imgs[imgn]->xsize, y, line);
+ for (x = 0; x < imgs[imgn]->xsize; ++x)
+ used[line[x]] = 1;
+ }
+
+ myfree(line);
+ }
+ else {
+ /* assume all are in use */
+ memset(used, 1, sizeof(used));
+ }
+
+ col_count = i_colorcount(imgs[imgn]);
+ for (i = 0; i < col_count; ++i) {
+ i_color c;
+
+ i_getcolors(imgs[imgn], i, &c, 1);
+ if (used[i]) {
+ if (in_palette(&c, quant, size) < 0) {
+ if (size < quant->mc_size) {
+ quant->mc_colors[size++] = c;
+ }
+ else {
+ mm_log((1, "makemap_palette() -> 0 (too many colors)\n"));
+ return 0;
+ }
+ }
+ }
+ }
+ }
+
+ mm_log((1, "makemap_palette() -> 1 (%d total colors)\n", size));
+ quant->mc_count = size;
+
+ return 1;
+}
+
#define pboxjump 32
/* Define one of the following 4 symbols to choose a colour search method
@@ -755,6 +870,23 @@ makemap_mono(i_quantize *quant) {
/*#define IM_CFRAND2DIST*/
#endif
+/* return true if the color map contains only grays */
+static int
+is_gray_map(const i_quantize *quant) {
+ int i;
+
+ for (i = 0; i < quant->mc_count; ++i) {
+ if (quant->mc_colors[i].rgb.r != quant->mc_colors[i].rgb.g
+ || quant->mc_colors[i].rgb.r != quant->mc_colors[i].rgb.b) {
+ mm_log((1, " not a gray map\n"));
+ return 0;
+ }
+ }
+
+ mm_log((1, " is a gray map\n"));
+ return 1;
+}
+
#ifdef IM_CFHASHBOX
/* The original version I wrote for this used the sort.
@@ -1205,6 +1337,7 @@ translate_errdiff(i_quantize *quant, i_img *img, i_palidx *out) {
int difftotal;
int x, y, dx, dy;
int bst_idx = 0;
+ int is_gray = is_gray_map(quant);
CF_VARS;
if ((quant->errdiff & ed_mask) == ed_custom) {
@@ -1249,6 +1382,10 @@ translate_errdiff(i_quantize *quant, i_img *img, i_palidx *out) {
if (img->channels < 3) {
val.channel[1] = val.channel[2] = val.channel[0];
}
+ else if (is_gray) {
+ int gray = 0.5 + color_to_grey(&val);
+ val.channel[0] = val.channel[1] = val.channel[2] = gray;
+ }
perr = err[x+mapo];
perr.r = perr.r < 0 ? -((-perr.r)/difftotal) : perr.r/difftotal;
perr.g = perr.g < 0 ? -((-perr.g)/difftotal) : perr.g/difftotal;
@@ -81,7 +81,7 @@ of the effect of the different alignments.
=head1 AUTHOR
-Tony Cook <tony@imager.perl.org>
+Tony Cook <tonyc@cpan.org>
=head1 SEE ALSO
@@ -145,7 +145,7 @@ Using JPEG as the output format is not recommended.
=head1 AUTHOR
-Tony Cook <tony@imager.perl.org>
+Tony Cook <tonyc@cpan.org>
=for stopwords Oppenheim
@@ -89,6 +89,6 @@ scale factor.
=head1 AUTHOR
-Tony Cook <tony@imager.perl.org>
+Tony Cook <tonyc@cpan.org>
=cut
@@ -86,7 +86,7 @@ http://www.perlmonks.org/?node_id=539316
=head1 AUTHOR
-Tony Cook <tony@imager.perl.org>
+Tony Cook <tonyc@cpan.org>
=head1 REVISION
@@ -122,7 +122,7 @@ might be useful.
=head1 AUTHOR
-Tony Cook <tony@imager.perl.org>
+Tony Cook <tonyc@cpan.org>
=for stopwords Oppenheim
@@ -78,7 +78,7 @@ cautions and explanations.
=head1 AUTHOR
-Tony Cook <tony@imager.perl.org>
+Tony Cook <tonyc@cpan.org>
=head1 REVISION
@@ -68,7 +68,7 @@ cautions and explanations.
=head1 AUTHOR
-Tony Cook <tony@imager.perl.org>
+Tony Cook <tonyc@cpan.org>
=head1 REVISION
@@ -205,7 +205,7 @@ cases the actual text will not be touching these boundaries.
=head1 AUTHOR
-Tony Cook <tony@imager.perl.org>
+Tony Cook <tonyc@cpan.org>
=head1 REVISION
@@ -64,6 +64,6 @@ $Revision$
=head1 AUTHOR
-Tony Cook <tony@imager.perl.org>
+Tony Cook <tonyc@cpan.org>
=cut
@@ -3,7 +3,7 @@
# to make sure we get expected values
use strict;
-use Test::More tests => 230;
+use Test::More tests => 233;
BEGIN { use_ok(Imager => qw(:handy :all)) }
@@ -11,7 +11,7 @@ use Imager::Test qw(image_bounds_checks is_color3 is_color4 is_fcolor4 color_cmp
-d "testout" or mkdir "testout";
-init_log("testout/t01introvert.log",1);
+Imager->open_log(log => "testout/t01introvert.log");
my $im_g = Imager::ImgRaw::new(100, 101, 1);
@@ -132,7 +132,8 @@ is(Imager::i_img_type($im_pal), 0, "pal img shouldn't be paletted now");
# test the OO interfaces
my $impal2 = Imager->new(type=>'pseudo', xsize=>200, ysize=>201);
-ok($impal2, "make paletted via OO");
+ok($impal2, "make paletted via OO")
+ or diag(Imager->errstr);
is($impal2->getchannels, 3, "check channels");
is($impal2->bits, 8, "check bits");
is($impal2->type, 'paletted', "check type");
@@ -167,7 +168,8 @@ is($impal2->getheight, 201, "check height");
"we can setcolors");
# make an rgb version
- my $imrgb2 = $impal2->to_rgb8();
+ my $imrgb2 = $impal2->to_rgb8()
+ or diag($impal2->errstr);
is($imrgb2->type, 'direct', "converted is direct");
# and back again, specifying the palette
@@ -183,6 +185,13 @@ is($impal2->getheight, 201, "check height");
is($impal3->type, 'paletted', "and is paletted");
}
+{ # to_rgb on incomplete image
+ my $im = Imager->new;
+ ok($im, "make empty image");
+ ok(!$im->to_rgb8, "convert to rgb8");
+ is($im->errstr, "empty input image", "check message");
+}
+
{ # basic checks, 8-bit direct images
my $im = Imager->new(xsize => 2, ysize => 3);
ok($im, 'create 8-bit direct image');
@@ -542,6 +551,12 @@ cmp_ok(Imager->errstr, '=~', qr/channels must be between 1 and 4/,
image_bounds_checks($im);
}
+Imager->close_log();
+
+unless ($ENV{IMAGER_KEEP_FILES}) {
+ unlink "testout/t01introvert.log";
+}
+
sub check_add {
my ($im, $color, $expected) = @_;
my $index = Imager::i_addcolors($im, $color);
@@ -6,7 +6,7 @@ use Imager::Test qw(is_color3 is_fcolor3);
-d "testout" or mkdir "testout";
-init_log("testout/t020masked.log", 1);
+Imager->open_log(log => "testout/t020masked.log");
my $base_rgb = Imager::ImgRaw::new(100, 100, 3);
# put something in there
@@ -529,3 +529,9 @@ $mask->box(fill => { hatch => "check1x1" }, ymin => 40, xmax => 39);
2, "write over right side");
}
}
+
+Imager->close_log();
+
+unless ($ENV{IMAGER_KEEP_FILES}) {
+ unlink "testout/t020masked.log";
+}
@@ -1,12 +1,12 @@
#!perl -w
use strict;
-use Test::More tests => 104;
+use Test::More tests => 107;
BEGIN { use_ok(Imager=>qw(:all :handy)) }
-d "testout" or mkdir "testout";
-init_log("testout/t021sixteen.log", 1);
+Imager->open_log(log => "testout/t021sixteen.log");
use Imager::Color::Float;
use Imager::Test qw(test_image is_image image_bounds_checks test_colorf_gpix
@@ -206,6 +206,13 @@ cmp_ok(Imager->errstr, '=~', qr/channels must be between 1 and 4/,
is_image($im, $im16, "check image data matches");
}
+{ # empty image handling
+ my $im = Imager->new;
+ ok($im, "make empty image");
+ ok(!$im->to_rgb16, "convert empty image to 16-bit");
+ is($im->errstr, "empty input image", "check message");
+}
+
{ # bounds checks
my $im = Imager->new(xsize => 10, ysize => 10, bits => 16);
image_bounds_checks($im);
@@ -223,3 +230,9 @@ cmp_ok(Imager->errstr, '=~', qr/channels must be between 1 and 4/,
or print "# ", $im->errstr, "\n";
is_deeply(\@wr_samples, \@samples, "check it matches");
}
+
+Imager->close_log;
+
+unless ($ENV{IMAGER_KEEP_FILES}) {
+ unlink "testout/t021sixteen.log";
+}
@@ -1,12 +1,13 @@
#!perl -w
use strict;
-use Test::More tests => 83;
-
+use Test::More tests => 88;
BEGIN { use_ok(Imager => qw(:all :handy)) }
+use Imager::Test qw(test_image is_image);
+
-d "testout" or mkdir "testout";
-init_log("testout/t022double.log", 1);
+Imager->open_log(log => "testout/t022double.log");
use Imager::Test qw(image_bounds_checks test_colorf_gpix test_colorf_glin mask_tests);
@@ -151,3 +152,25 @@ cmp_ok(Imager->errstr, '=~', qr/channels must be between 1 and 4/,
my $im = Imager->new(xsize => 10, ysize=>10, bits=>'double');
image_bounds_checks($im);
}
+
+
+{ # convert to rgb double
+ my $im = test_image();
+ my $imdb = $im->to_rgb_double;
+ print "# check conversion to double\n";
+ is($imdb->bits, "double", "check bits");
+ is_image($im, $imdb, "check image data matches");
+}
+
+{ # empty image handling
+ my $im = Imager->new;
+ ok($im, "make empty image");
+ ok(!$im->to_rgb_double, "convert empty image to double");
+ is($im->errstr, "empty input image", "check message");
+}
+
+Imager->close_log;
+
+unless ($ENV{IMAGER_KEEP_FILES}) {
+ unlink "testout/t022double.log";
+}
@@ -1,10 +1,12 @@
#!perl -w
# some of this is tested in t01introvert.t too
use strict;
-use Test::More tests => 126;
+use Test::More tests => 128;
BEGIN { use_ok("Imager"); }
-use Imager::Test qw(image_bounds_checks test_image is_color3);
+use Imager::Test qw(image_bounds_checks test_image is_color3 isnt_image);
+
+Imager->open_log(log => "testout/t023palette.log");
sub isbin($$$);
@@ -343,6 +345,21 @@ cmp_ok(Imager->errstr, '=~', qr/Channels must be positive and <= 4/,
is_color3($colors[8], 0, 0x33, 0x66, "9th should be 003366");
}
+{ # RT 68508
+ my $im = Imager->new(xsize => 10, ysize => 10);
+ $im->box(filled => 1, color => Imager::Color->new(255, 0, 0));
+ my $palim = $im->to_paletted(make_colors => "mono", translate => "errdiff");
+ ok($palim, "convert to mono with error diffusion");
+ my $blank = Imager->new(xsize => 10, ysize => 10);
+ isnt_image($palim, $blank, "make sure paletted isn't all black");
+}
+
+Imager->close_log;
+
+unless ($ENV{IMAGER_KEEP_FILES}) {
+ unlink "testout/t023palette.log"
+}
+
sub iscolor {
my ($c1, $c2, $msg) = @_;
@@ -1,12 +1,11 @@
-BEGIN { $|=1; print "1..2\n"; }
-END { print "not ok 1\n" unless $loaded; };
-use Imager qw(:all);
-++$loaded;
-print "ok 1\n";
+#!perl -w
+use strict;
+use Test::More tests => 7;
+BEGIN { use_ok("Imager", ":all") }
-d "testout" or mkdir "testout";
-init_log("testout/t05error.log", 1);
+Imager->open_log(log => "testout/t05error.log");
# try to read an invalid pnm file
open FH, "< testimg/junk.ppm"
@@ -14,34 +13,31 @@ open FH, "< testimg/junk.ppm"
binmode(FH);
my $IO = Imager::io_new_fd(fileno(FH));
my $im = i_readpnm_wiol($IO, -1);
-if ($im) {
- print "not ok 2 # read of junk.ppm should have failed\n";
-}
-else {
+SKIP:{
+ ok(!$im, "read of junk.ppm should have failed")
+ or skip("read didn't fail!", 5);
+
my @errors = Imager::i_errors();
- unless (@errors) {
- print "not ok 2 # no errors from i_errors()\n";
- }
- else {
- # each entry must be an array ref with 2 elements
- my $bad;
- for (@errors) {
- $bad = 1;
- if (ref ne 'ARRAY') {
- print "not ok 2 # element not an array ref\n";
- last;
- }
- if (@$_ != 2) {
- print "not ok 2 # elements array didn't have 2 elements\n";
- last;
- }
- $bad = 0;
- }
- unless ($bad) {
- print "ok 2\n";
- for (@errors) {
- print "# $_->[0]/$_->[1]\n";
- }
- }
+
+ is(scalar @errors, 1, "got the errors")
+ or skip("no errors to check", 4);
+
+ SKIP:
+ {
+ my $error0 = $errors[0];
+ is(ref $error0, "ARRAY", "entry 0 is an array ref")
+ or skip("entry 0 not an array", 3);
+
+ is(scalar @$error0, 2, "entry 0 has 2 elements")
+ or skip("entry 0 doesn't have enough elements", 2);
+
+ is($error0->[0], "while skipping to height", "check message");
+ is($error0->[1], "0", "error code should be 0");
}
}
+
+Imager->close_log;
+
+unless ($ENV{IMAGER_KEEP_FILES}) {
+ unlink "testout/t05error.log";
+}
@@ -8,7 +8,7 @@ BEGIN { use_ok(Imager => ':all') };
-d "testout" or mkdir "testout";
-init_log("testout/t07iolayer.log", 1);
+Imager->open_log(log => "testout/t07iolayer.log");
undef($/);
# start by testing io buffer
@@ -252,6 +252,12 @@ SKIP:
is($io->close, 0, "close");
}
+Imager->close_log;
+
+unless ($ENV{IMAGER_KEEP_FILES}) {
+ unlink "testout/t07.ppm", "testout/t07iolayer.log";
+}
+
sub eof_read {
my ($max_len) = @_;
@@ -9,7 +9,7 @@ use Imager;
-d "testout" or mkdir "testout";
-Imager::init_log("testout/t1000files.log", 1);
+Imager->open_log(log => "testout/t1000files.log");
SKIP:
{
@@ -186,6 +186,12 @@ probe_ok(<<JPEG2K, "jp2", "JPEG 2000");
00 6A 70 32 63 FF 4F FF 51 00 2F 00 00 00 00 01
JPEG2K
+Imager->close_log;
+
+unless ($ENV{IMAGER_KEEP_FILES}) {
+ unlink "testout/t1000files.log";
+}
+
sub probe_ok {
my ($packed, $exp_type, $name) = @_;
@@ -5,7 +5,7 @@ use Imager qw(:all);
-d "testout" or mkdir "testout";
-init_log("testout/t101jpeg.log",1);
+Imager->open_log(log => "testout/t101jpeg.log");
$Imager::formats{"jpeg"}
and plan skip_all => "have jpeg support - this tests the lack of it";
@@ -20,3 +20,9 @@ ok(!$im->write(file=>"testout/nojpeg.jpg"), "should fail to write jpeg");
cmp_ok($im->errstr, '=~', qr/format 'jpeg' not supported/, "check no jpeg message");
ok(!grep($_ eq 'jpeg', Imager->read_types), "check jpeg not in read types");
ok(!grep($_ eq 'jpeg', Imager->write_types), "check jpeg not in write types");
+
+Imager->close_log;
+
+unless ($ENV{IMAGER_KEEP_FILES}) {
+ unlink "testout/t101jpeg.log";
+}
@@ -6,7 +6,7 @@ use Imager::Test qw/is_color3 is_color4/;
-d "testout" or mkdir "testout";
-init_log("testout/t103raw.log",1);
+Imager->open_log(log => "testout/t103raw.log");
$| = 1;
@@ -270,9 +270,13 @@ SKIP:
"check last channel zeroed");
}
-unlink(qw(testout/t103_base.raw testout/t103_3to4.raw
- testout/t103_line_int.raw testout/t103_img_int.raw))
- unless $ENV{IMAGER_KEEP_FILES};
+Imager->close_log;
+
+unless ($ENV{IMAGER_KEEP_FILES}) {
+ unlink "testout/t103raw.log";
+ unlink(qw(testout/t103_base.raw testout/t103_3to4.raw
+ testout/t103_line_int.raw testout/t103_img_int.raw))
+}
sub read_test {
my ($in, $xsize, $ysize, $data, $store, $intrl, $base) = @_;
@@ -6,15 +6,18 @@ use Imager::Test qw(test_image_raw test_image_16 is_color3 is_color1 is_image);
-d "testout" or mkdir "testout";
-init_log("testout/t104ppm.log",1);
+Imager->open_log(log => "testout/t104ppm.log");
my $green = i_color_new(0,255,0,255);
my $blue = i_color_new(0,0,255,255);
my $red = i_color_new(255,0,0,255);
+my @files;
+
my $img = test_image_raw();
my $fh = openimage(">testout/t104.ppm");
+push @files, "t104.ppm";
my $IO = Imager::io_new_fd(fileno($fh));
ok(i_writeppm_wiol($img, $IO), "write pnm low")
or die "Cannot write testout/t104.ppm\n";
@@ -46,6 +49,7 @@ i_box_filled($gimg, 20, 20, 130, 130, $gray);
i_box_filled($gimg, 40, 40, 110, 110, $dgray);
i_arc($gimg, 75, 75, 30, 0, 361, $white);
+push @files, "t104_gray.pgm";
open FH, "> testout/t104_gray.pgm" or die "Cannot create testout/t104_gray.pgm: $!\n";
binmode FH;
$IO = Imager::io_new_fd(fileno(FH));
@@ -225,6 +229,7 @@ is($ooim->tags(name=>'pnm_type'), 1, "check pnm_type tag");
$im->box(filled => 1, xmin => 8, color => '#FFE0C0');
$im->box(filled => 1, color => NC(0, 192, 192, 128),
ymin => 8, xmax => 7);
+ push @files, "t104_alpha.ppm";
ok($im->write(file=>"testout/t104_alpha.ppm", type=>'pnm'),
"should succeed writing 4 channel image");
my $imread = Imager->new;
@@ -254,6 +259,7 @@ is($ooim->tags(name=>'pnm_type'), 1, "check pnm_type tag");
$im->box(filled => 1, xmin => 8, color => '#FFE0C0');
$im->box(filled => 1, color => NC(0, 192, 192, 128),
ymin => 8, xmax => 7);
+ push @files, "t104_alp16.ppm";
ok($im->write(file=>"testout/t104_alp16.ppm", type=>'pnm',
pnm_write_wide_data => 1),
"should succeed writing 4 channel image");
@@ -493,6 +499,7 @@ print "# check error handling\n";
$im->box(filled => 1, xmax => 4, color => '#000000');
$im->box(filled => 1, xmin => 5, color => '#FFFFFF');
is($im->type, 'paletted', 'mono still paletted');
+ push @files, "t104_mono.pbm";
ok($im->write(file => 'testout/t104_mono.pbm', type => 'pnm'),
"save as pbm");
@@ -514,6 +521,7 @@ print "# check error handling\n";
$im->box(filled => 1, xmax => 4, color => '#000000');
$im->box(filled => 1, xmin => 5, color => '#FFFFFF');
is($im->type, 'paletted', 'mono still paletted');
+ push @files, "t104_mono2.pbm";
ok($im->write(file => 'testout/t104_mono2.pbm', type => 'pnm'),
"save as pbm");
@@ -545,10 +553,12 @@ print "# check error handling\n";
$data = '';
ok($im->write(data => \$data, type => 'pnm'),
"write 16-bit image as 16-bit/sample ppm");
+ push @files, "t104_16.ppm";
$im->write(file=>'testout/t104_16.ppm');
my $im16 = Imager->new;
ok($im16->read(data => $data), "read it back");
is($im16->tags(name => 'pnm_maxval'), 65535, "check maxval");
+ push @files, "t104_16b.ppm";
$im16->write(file=>'testout/t104_16b.ppm');
is_image($im, $im16, "check image matches");
}
@@ -584,6 +594,13 @@ print "# check error handling\n";
}
}
+Imager->close_log;
+
+unless ($ENV{IMAGER_KEEP_FILES}) {
+ unlink "testout/t104ppm.log";
+ unlink map "testout/$_", @files;
+}
+
sub openimage {
my $fname = shift;
local(*FH);
@@ -6,8 +6,9 @@ use Imager::Test qw(test_image_raw is_image is_color3 test_image);
-d "testout" or mkdir "testout";
-init_log("testout/t107bmp.log",1);
+Imager->open_log(log => "testout/t107bmp.log");
+my @files;
my $debug_writes = 0;
my $base_diff = 0;
@@ -21,10 +22,12 @@ my $img = test_image_raw();
Imager::i_tags_add($img, 'i_xres', 0, '300', 0);
Imager::i_tags_add($img, 'i_yres', 0, undef, 300);
write_test($img, "testout/t107_24bit.bmp");
+push @files, "t107_24bit.bmp";
# 'webmap' is noticably faster than the default
my $im8 = Imager::i_img_to_pal($img, { make_colors=>'webmap',
translate=>'errdiff'});
write_test($im8, "testout/t107_8bit.bmp");
+push @files, "t107_8bit.bmp";
# use a fixed palette so we get reproducible results for the compressed
# version
my @pal16 = map { NC($_) }
@@ -32,9 +35,11 @@ my @pal16 = map { NC($_) }
2ead1b 0000f8 004b01 fd0000 0e1695 000002);
my $im4 = Imager::i_img_to_pal($img, { colors=>\@pal16, make_colors=>'none' });
write_test($im4, "testout/t107_4bit.bmp");
+push @files, "t107_4bit.bmp";
my $im1 = Imager::i_img_to_pal($img, { colors=>[ NC(0, 0, 0), NC(176, 160, 144) ],
make_colors=>'none', translate=>'errdiff' });
write_test($im1, "testout/t107_1bit.bmp");
+push @files, "t107_1bit.bmp";
my $bi_rgb = 0;
my $bi_rle8 = 1;
my $bi_rle4 = 2;
@@ -62,6 +67,7 @@ ok($imoo->read(file=>'testout/t107_24bit.bmp'), "read via OO")
ok($imoo->write(file=>'testout/t107_oo.bmp'), "write via OO")
or print "# ",$imoo->errstr,"\n";
+push @files, "t107_oo.bmp";
# various invalid format tests
# we have so many different test images to try to detect all the possible
@@ -629,6 +635,7 @@ for my $comp (@comp) {
ymin => 8, xmax => 7);
ok($im->write(file=>"testout/t107_alpha.bmp", type=>'bmp'),
"should succeed writing 4 channel image");
+ push @files, "t107_alpha.bmp";
my $imread = Imager->new;
ok($imread->read(file => 'testout/t107_alpha.bmp'), "read it back");
is_color3($imread->getpixel('x' => 0, 'y' => 0), 0, 0, 0,
@@ -658,6 +665,13 @@ for my $comp (@comp) {
is($size, 67800, "check data size");
}
+Imager->close_log;
+
+unless ($ENV{IMAGER_KEEP_FILES}) {
+ unlink map "testout/$_", @files;
+ unlink "testout/t107bmp.log";
+}
+
sub write_test {
my ($im, $filename) = @_;
local *FH;
@@ -14,7 +14,7 @@ use Imager::Test qw(is_fcolor4);
-d "testout" or mkdir "testout";
-init_log("testout/t15color.log",1);
+Imager->open_log(log => "testout/t15color.log");
my $c1 = Imager::Color->new(100, 150, 200, 250);
ok(test_col($c1, 100, 150, 200, 250), 'simple 4-arg');
@@ -16,7 +16,7 @@ BEGIN { use_ok('Imager') };
-d "testout" or mkdir "testout";
-init_log("testout/t36oofont.log", 1);
+Imager->open_log(log => "testout/t36oofont.log");
my $fontname_tt=$ENV{'TTFONTTEST'}||'./fontfiles/dodge.ttf';
@@ -1,55 +1,50 @@
-BEGIN { $| = 1; print "1..5\n"; }
-END {print "not ok 1\n" unless $loaded;}
+#!perl -w
+use strict;
+use Test::More;
use Imager;
-$loaded = 1;
+eval "use Affix::Infix2Postfix; 1;"
+ or plan skip_all => "No Affix::Infix2Postfix";
+
+plan tests => 6;
#$Imager::DEBUG=1;
-d "testout" or mkdir "testout";
-Imager::init('log'=>'testout/t55trans.log');
-
-$img=Imager->new() || die "unable to create image object\n";
-
-print "ok 1\n";
+Imager->open_log('log'=>'testout/t55trans.log');
-$img->open(file=>'testimg/scale.ppm',type=>'pnm');
+my $img=Imager->new();
-sub skip {
- print "ok 2 # skip $_[0]\n";
- print "ok 3 # skip $_[0]\n";
- print "ok 4 # skip $_[0]\n";
- print "ok 5 # skip $_[0]\n";
- exit(0);
-}
+SKIP:
+{
+ ok($img, "make image object")
+ or skip("can't make image object", 5);
+ ok($img->open(file=>'testimg/scale.ppm',type=>'pnm'),
+ "read sample image")
+ or skip("couldn't load test image", 4);
-$nimg=$img->transform(xexpr=>'x',yexpr=>'y+10*sin((x+y)/10)') || skip ( "\# warning ".$img->{'ERRSTR'} );
+ SKIP:
+ {
+ my $nimg=$img->transform(xexpr=>'x',yexpr=>'y+10*sin((x+y)/10)');
+ ok($nimg, "do transformation")
+ or skip ( "warning ".$img->errstr, 1 );
-# xopcodes=>[qw( x y Add)],yopcodes=>[qw( x y Sub)],parm=>[]
+ # xopcodes=>[qw( x y Add)],yopcodes=>[qw( x y Sub)],parm=>[]
-print "ok 2\n";
-$nimg->write(type=>'pnm',file=>'testout/t55.ppm') || die "error in write()\n";
+ ok($nimg->write(type=>'pnm',file=>'testout/t55.ppm'), "save to file");
+ }
-print "ok 3\n";
+ SKIP:
+ {
+ my $nimg=$img->transform(xexpr=>'x+0.1*y+5*sin(y/10.0+1.57)',
+ yexpr=>'y+10*sin((x+y-0.785)/10)');
+ ok($nimg, "more complex transform")
+ or skip("couldn't make image", 1);
-# the original test didn't produce many parameters - this one
-# produces more parameters, which revealed a memory allocation bug
-# (sizeof(double) vs sizeof(int))
-sub skip2 {
- print "ok 4 # skip $_[0]\n";
- print "ok 5 # skip $_[0]\n";
- exit(0);
+ ok($nimg->write(type=>'pnm',file=>'testout/t55b.ppm'), "save to file");
+ }
}
-$nimg=$img->transform(xexpr=>'x+0.1*y+5*sin(y/10.0+1.57)',
- yexpr=>'y+10*sin((x+y-0.785)/10)')
- || skip2 ( "\# warning ".$img->{'ERRSTR'} );
-
-print "ok 4\n";
-$nimg->write(type=>'pnm',file=>'testout/t55b.ppm')
- || die "error in write()\n";
-
-print "ok 5\n";
@@ -17,7 +17,6 @@ my @private =
'^DSO_',
'^Inline$',
'^yatf$',
- '^m_init_log$',
'^malloc_state$',
'^init_log$',
'^polybezier$', # not ready for public consumption
@@ -0,0 +1,34 @@
+#!perl -w
+use strict;
+use Imager;
+use Test::More tests => 6;
+
+my $log_name = "testout/t95log.log";
+
+my $log_message = "test message 12345";
+
+SKIP: {
+ skip("Logging not build", 3)
+ unless Imager::i_log_enabled();
+ ok(Imager->open_log(log => $log_name), "open log")
+ or diag("Open log: " . Imager->errstr);
+ ok(-f $log_name, "file is there");
+ Imager->log($log_message);
+ Imager->close_log();
+
+ my $data = '';
+ if (open LOG, "< $log_name") {
+ $data = do { local $/; <LOG> };
+ close LOG;
+ }
+ like($data, qr/\Q$log_message/, "check message made it to the log");
+}
+
+SKIP: {
+ skip("Logging built", 3)
+ if Imager::i_log_enabled();
+
+ ok(!Imager->open_log(log => $log_name), "should be no logfile");
+ is(Imager->errstr, "Logging disabled", "check error message");
+ ok(!-f $log_name, "file shouldn't be there");
+}
@@ -0,0 +1,19 @@
+#!perl -w
+use strict;
+use Test::More;
+plan skip_all => "Only run as part of the dist"
+ unless -f "META.yml";
+eval "use CPAN::Meta 2.0;";
+plan skip_all => "CPAN::Meta required for testing META.yml"
+ if $@;
+plan skip_all => "Only if automated or author testing"
+ unless $ENV{AUTOMATED_TESTING} || -d "../.git";
+plan tests => 1;
+
+my $meta;
+unless (ok(eval {
+ $meta = CPAN::Meta->load_file("META.yml",
+ { lazy_validation => 0 }) },
+ "loaded META.yml successfully")) {
+ diag($@);
+}